@nocobase/plugin-flow-engine 2.1.0-beta.35 → 2.1.0-beta.37

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 (68) hide show
  1. package/dist/externalVersion.js +9 -9
  2. package/dist/node_modules/@ant-design/icons-svg/package.json +1 -1
  3. package/dist/node_modules/acorn/LICENSE +21 -0
  4. package/dist/node_modules/acorn/bin/acorn +4 -0
  5. package/dist/node_modules/acorn/dist/acorn.d.mts +857 -0
  6. package/dist/node_modules/acorn/dist/acorn.d.ts +857 -0
  7. package/dist/node_modules/acorn/dist/acorn.js +1 -0
  8. package/dist/node_modules/acorn/dist/bin.js +90 -0
  9. package/dist/node_modules/acorn/package.json +1 -0
  10. package/dist/node_modules/acorn-jsx/LICENSE +19 -0
  11. package/dist/node_modules/acorn-jsx/index.d.ts +12 -0
  12. package/dist/node_modules/acorn-jsx/index.js +1 -0
  13. package/dist/node_modules/acorn-jsx/package.json +1 -0
  14. package/dist/node_modules/acorn-jsx/xhtml.js +255 -0
  15. package/dist/node_modules/acorn-walk/LICENSE +21 -0
  16. package/dist/node_modules/acorn-walk/dist/walk.d.mts +177 -0
  17. package/dist/node_modules/acorn-walk/dist/walk.d.ts +177 -0
  18. package/dist/node_modules/acorn-walk/dist/walk.js +1 -0
  19. package/dist/node_modules/acorn-walk/node_modules/acorn/bin/acorn +4 -0
  20. package/dist/node_modules/acorn-walk/node_modules/acorn/dist/acorn.d.mts +866 -0
  21. package/dist/node_modules/acorn-walk/node_modules/acorn/dist/acorn.d.ts +866 -0
  22. package/dist/node_modules/acorn-walk/node_modules/acorn/dist/acorn.js +6174 -0
  23. package/dist/node_modules/acorn-walk/node_modules/acorn/dist/bin.js +90 -0
  24. package/dist/node_modules/acorn-walk/node_modules/acorn/package.json +50 -0
  25. package/dist/node_modules/acorn-walk/package.json +1 -0
  26. package/dist/node_modules/ses/package.json +1 -1
  27. package/dist/node_modules/zod/package.json +1 -1
  28. package/dist/server/flow-surfaces/action-scope.d.ts +2 -0
  29. package/dist/server/flow-surfaces/action-scope.js +8 -0
  30. package/dist/server/flow-surfaces/authoring-validation.d.ts +3 -0
  31. package/dist/server/flow-surfaces/authoring-validation.js +317 -9
  32. package/dist/server/flow-surfaces/blueprint/compile-blocks.js +143 -3
  33. package/dist/server/flow-surfaces/blueprint/public-types.d.ts +1 -1
  34. package/dist/server/flow-surfaces/builder.js +54 -1
  35. package/dist/server/flow-surfaces/catalog.js +158 -2
  36. package/dist/server/flow-surfaces/chart-config.d.ts +58 -54
  37. package/dist/server/flow-surfaces/chart-config.js +18 -5
  38. package/dist/server/flow-surfaces/compose-compiler.d.ts +1 -1
  39. package/dist/server/flow-surfaces/compose-runtime.d.ts +1 -0
  40. package/dist/server/flow-surfaces/compose-runtime.js +24 -6
  41. package/dist/server/flow-surfaces/configure-options.js +40 -1
  42. package/dist/server/flow-surfaces/default-block-actions.js +11 -0
  43. package/dist/server/flow-surfaces/index.js +4 -2
  44. package/dist/server/flow-surfaces/node-use-sets.js +2 -0
  45. package/dist/server/flow-surfaces/runjs-authoring/ctx-libs-member-mismatch-stop/index.js +1 -1
  46. package/dist/server/flow-surfaces/runjs-authoring/index.d.ts +14 -2
  47. package/dist/server/flow-surfaces/runjs-authoring/index.js +4633 -252
  48. package/dist/server/flow-surfaces/runjs-authoring/nested-runjs-stop/index.d.ts +10 -0
  49. package/dist/server/flow-surfaces/runjs-authoring/nested-runjs-stop/index.js +40 -0
  50. package/dist/server/flow-surfaces/runjs-authoring/rules.js +6 -0
  51. package/dist/server/flow-surfaces/runjs-authoring/source-limit-stop/index.d.ts +10 -0
  52. package/dist/server/flow-surfaces/runjs-authoring/source-limit-stop/index.js +40 -0
  53. package/dist/server/flow-surfaces/runjs-authoring/syntax-stop/index.d.ts +10 -0
  54. package/dist/server/flow-surfaces/runjs-authoring/syntax-stop/index.js +40 -0
  55. package/dist/server/flow-surfaces/runjs-authoring/types.d.ts +1 -1
  56. package/dist/server/flow-surfaces/service-utils.d.ts +1 -1
  57. package/dist/server/flow-surfaces/service-utils.js +3 -0
  58. package/dist/server/flow-surfaces/service.d.ts +106 -17
  59. package/dist/server/flow-surfaces/service.js +1760 -131
  60. package/dist/server/flow-surfaces/support-matrix.d.ts +1 -1
  61. package/dist/server/flow-surfaces/support-matrix.js +13 -1
  62. package/dist/server/flow-surfaces/surface-context.js +4 -13
  63. package/dist/swagger/flow-surfaces.d.ts +148 -0
  64. package/dist/swagger/flow-surfaces.examples.d.ts +179 -1
  65. package/dist/swagger/flow-surfaces.examples.js +75 -3
  66. package/dist/swagger/flow-surfaces.js +181 -7
  67. package/dist/swagger/index.d.ts +148 -0
  68. package/package.json +5 -2
@@ -146,10 +146,24 @@ const CANONICAL_BLOCK_HEADER_USES = /* @__PURE__ */ new Set([
146
146
  "ChartBlockModel",
147
147
  "ActionPanelBlockModel",
148
148
  "MapBlockModel",
149
- "CommentsBlockModel"
149
+ "CommentsBlockModel",
150
+ "RecordHistoryBlockModel"
150
151
  ]);
152
+ const COMMENTS_PAGE_SIZE_VALUES = /* @__PURE__ */ new Set([5, 10, 20, 50, 100, 200]);
153
+ const RECORD_HISTORY_INTERNAL_COLLECTIONS = /* @__PURE__ */ new Set(["recordHistories", "recordFieldHistories"]);
151
154
  const CARD_FIELD_COMPOSE_BLOCK_TYPES = /* @__PURE__ */ new Set(["list", "gridCard", "kanban"]);
152
- const RECORD_ACTION_COMPOSE_BLOCK_TYPES = /* @__PURE__ */ new Set(["list", "gridCard"]);
155
+ const RECORD_ACTION_COMPOSE_BLOCK_TYPES = /* @__PURE__ */ new Set(["list", "gridCard", "comments"]);
156
+ const COMMENT_ACTION_SINGLETON_USES = /* @__PURE__ */ new Set([
157
+ "EditCommentActionModel",
158
+ "DeleteCommentActionModel",
159
+ "QuoteReplyActionModel"
160
+ ]);
161
+ const RECORD_HISTORY_ACTION_SINGLETON_USES = /* @__PURE__ */ new Set([
162
+ "FilterActionModel",
163
+ "RefreshActionModel",
164
+ "RecordHistoryExpandActionModel",
165
+ "RecordHistoryCollapseActionModel"
166
+ ]);
153
167
  const GRID_SETTINGS_FLOW_KEY = "gridSettings";
154
168
  const GRID_SETTINGS_LAYOUT_STEP_KEY = "grid";
155
169
  const OPEN_VIEW_MODE_ALIASES = {
@@ -167,7 +181,8 @@ const FILTER_TARGET_BLOCK_USES = /* @__PURE__ */ new Set([
167
181
  "GridCardBlockModel",
168
182
  "ChartBlockModel",
169
183
  "MapBlockModel",
170
- "CommentsBlockModel"
184
+ "CommentsBlockModel",
185
+ "RecordHistoryBlockModel"
171
186
  ]);
172
187
  const TREE_CONNECT_TARGET_BLOCK_USES = new Set(FILTER_TARGET_BLOCK_USES);
173
188
  const EDITABLE_FIELD_WRAPPER_USES = /* @__PURE__ */ new Set(["FormItemModel", "FilterFormItemModel", "PatternFormItemModel"]);
@@ -315,6 +330,7 @@ const POPUP_COLLECTION_BLOCK_SCENES = {
315
330
  ProcessFormModel: ["one"],
316
331
  ApprovalDetailsModel: ["one"],
317
332
  CommentsBlockModel: ["one", "many"],
333
+ RecordHistoryBlockModel: ["one", "many"],
318
334
  TableBlockModel: ["many"],
319
335
  CalendarBlockModel: ["many"],
320
336
  TreeBlockModel: ["filter"],
@@ -441,6 +457,25 @@ const UPDATE_SETTINGS_STEP_PARAM_MIRRORS_BY_USE = {
441
457
  DividerItemModel: DIVIDER_ITEM_STEP_PARAM_MIRRORS
442
458
  };
443
459
  const FLOW_SURFACE_MENU_BINDABLE_OPTION_KEY = "flowSurfaceMenuBindable";
460
+ const AI_EMPLOYEE_ACTION_USE = "AIEmployeeButtonModel";
461
+ const AI_EMPLOYEE_OWNER_PLUGIN = "@nocobase/plugin-ai";
462
+ const AI_EMPLOYEE_PUBLIC_SETTING_KEYS = ["username", "auto", "workContext", "tasks", "style"];
463
+ const AI_EMPLOYEE_INTERNAL_PROP_KEYS = ["aiEmployee", "context", "auto", "tasks", "style"];
464
+ const AI_EMPLOYEE_TASK_STEP_PARAMS_PATH = ["shortcutSettings", "editTasks", "tasks"];
465
+ const AI_EMPLOYEE_WORK_CONTEXT_PUBLIC_KEYS = ["type", "uid", "target"];
466
+ const AI_EMPLOYEE_TASK_PUBLIC_SETTING_KEYS = ["title", "message", "autoSend", "skillSettings", "model", "webSearch"];
467
+ const AI_EMPLOYEE_TASK_MESSAGE_PUBLIC_KEYS = ["system", "user", "workContext"];
468
+ const AI_EMPLOYEE_TASK_MODEL_PUBLIC_KEYS = ["llmService", "model"];
469
+ const AI_EMPLOYEE_SKILL_SETTINGS_PUBLIC_KEYS = ["skills", "tools", "skillsVersion", "toolsVersion"];
470
+ const AI_EMPLOYEE_STYLE_PUBLIC_KEYS = ["size", "mask"];
471
+ const AI_EMPLOYEE_PROMPT_CONTEXT_MAX_DEPTH = 8;
472
+ const AI_EMPLOYEE_PROMPT_VARIABLE_INVALID = "FLOW_SURFACE_AI_EMPLOYEE_PROMPT_VARIABLE_INVALID";
473
+ const AI_EMPLOYEE_CURRENT_RECORD_PROMPT_VARIABLE = "{{ ctx.record }}";
474
+ const AI_EMPLOYEE_CURRENT_RECORD_PROMPT_VARIABLE_RE = /\{\{\s*ctx\.record\s*\}\}/;
475
+ const AI_EMPLOYEE_DEFAULT_STYLE = {
476
+ size: 40,
477
+ mask: false
478
+ };
444
479
  function normalizeCalendarFieldCapabilityValues(source, defaults) {
445
480
  const rawValues = Array.isArray(source) ? source : source instanceof Set ? Array.from(source) : typeof source === "string" ? [source] : source && typeof source === "object" ? Object.keys(source) : [];
446
481
  const values = rawValues.map((item) => String(item || "").trim()).filter(Boolean);
@@ -680,10 +715,16 @@ class FlowSurfacesService {
680
715
  );
681
716
  }
682
717
  async loadEnabledPluginPackages(transaction) {
683
- if (!this.db.getCollection("applicationPlugins")) {
718
+ var _a;
719
+ const db = this.db;
720
+ if (!((_a = db == null ? void 0 : db.getCollection) == null ? void 0 : _a.call(db, "applicationPlugins")) || !(db == null ? void 0 : db.getRepository)) {
721
+ return /* @__PURE__ */ new Set();
722
+ }
723
+ const repository = db.getRepository("applicationPlugins");
724
+ if (!(repository == null ? void 0 : repository.find)) {
684
725
  return /* @__PURE__ */ new Set();
685
726
  }
686
- const plugins = await this.db.getRepository("applicationPlugins").find({
727
+ const plugins = await repository.find({
687
728
  fields: ["packageName"],
688
729
  filter: {
689
730
  enabled: true
@@ -691,8 +732,8 @@ class FlowSurfacesService {
691
732
  transaction
692
733
  });
693
734
  const packageNames = plugins.map((plugin) => {
694
- var _a;
695
- return ((_a = plugin == null ? void 0 : plugin.get) == null ? void 0 : _a.call(plugin, "packageName")) || (plugin == null ? void 0 : plugin.packageName);
735
+ var _a2;
736
+ return ((_a2 = plugin == null ? void 0 : plugin.get) == null ? void 0 : _a2.call(plugin, "packageName")) || (plugin == null ? void 0 : plugin.packageName);
696
737
  }).filter((packageName) => typeof packageName === "string" && !!packageName.trim()).map((packageName) => packageName.trim());
697
738
  return new Set(packageNames);
698
739
  }
@@ -1456,12 +1497,26 @@ class FlowSurfacesService {
1456
1497
  if (this.isPopupCollectionBlockSceneUnsupported(popupProfile.scene)) {
1457
1498
  return [];
1458
1499
  }
1500
+ const associationFields = this.listPopupAssociatedRecordFields(popupProfile, blockUse);
1501
+ if (blockUse === "CommentsBlockModel") {
1502
+ if (!popupProfile.currentCollection || !popupProfile.hasCurrentRecord || !associationFields.length) {
1503
+ return [];
1504
+ }
1505
+ return [
1506
+ {
1507
+ key: "associatedRecords",
1508
+ label: "Associated records",
1509
+ description: "Bind comments to a comment-template association of the popup current record.",
1510
+ requires: ["associationField"],
1511
+ associationFields
1512
+ }
1513
+ ];
1514
+ }
1459
1515
  const bindings = [];
1460
1516
  const currentCollectionName = popupProfile.currentCollection ? popupProfile.collectionName || (0, import_service_helpers.getCollectionTitle)(popupProfile.currentCollection) : void 0;
1461
1517
  const blockScenes = this.getPopupCollectionBlockScenes(blockUse);
1462
1518
  const supportsCurrentCollection = blockScenes.includes("new") || !popupProfile.hasCurrentRecord && blockScenes.includes("many");
1463
- const supportsCurrentRecord = blockScenes.includes("one");
1464
- const associationFields = this.listPopupAssociatedRecordFields(popupProfile, blockUse);
1519
+ const supportsCurrentRecord = blockScenes.includes("one") && (blockUse !== "RecordHistoryBlockModel" || popupProfile.scene === "one");
1465
1520
  if (!popupProfile.currentCollection) {
1466
1521
  bindings.push({
1467
1522
  key: "otherRecords",
@@ -1521,7 +1576,11 @@ class FlowSurfacesService {
1521
1576
  popupProfile.dataSourceKey || "main",
1522
1577
  (dataSourceKey, collectionName) => this.getCollection(dataSourceKey, collectionName)
1523
1578
  );
1524
- if (!(targetCollection == null ? void 0 : targetCollection.filterTargetKey)) {
1579
+ if (blockUse === "CommentsBlockModel") {
1580
+ if (!this.isCommentsAssociationField(field, targetCollection)) {
1581
+ return null;
1582
+ }
1583
+ } else if (!(targetCollection == null ? void 0 : targetCollection.filterTargetKey)) {
1525
1584
  return null;
1526
1585
  }
1527
1586
  const associationName = (0, import_service_helpers.resolveAssociationNameFromField)(field, popupProfile.currentCollection);
@@ -1601,7 +1660,10 @@ class FlowSurfacesService {
1601
1660
  hostDataSourceKey: popupProfile.dataSourceKey,
1602
1661
  hostCollectionName: popupProfile.collectionName,
1603
1662
  currentDataSourceKey: popupProfile.dataSourceKey,
1604
- currentCollectionName: popupProfile.collectionName
1663
+ currentCollectionName: popupProfile.collectionName,
1664
+ isPopupSurface: popupProfile.isPopupSurface,
1665
+ popupScene: popupProfile.scene,
1666
+ popupHasCurrentRecord: popupProfile.hasCurrentRecord
1605
1667
  });
1606
1668
  }
1607
1669
  async buildTargetAuthoringContext(input) {
@@ -1660,6 +1722,9 @@ class FlowSurfacesService {
1660
1722
  popupProfile.dataSourceKey || "main",
1661
1723
  (dataSourceKey, collectionName) => this.getCollection(dataSourceKey, collectionName)
1662
1724
  );
1725
+ if (blockUse === "CommentsBlockModel") {
1726
+ return this.isCommentsAssociationField(field, targetCollection);
1727
+ }
1663
1728
  return !!(targetCollection == null ? void 0 : targetCollection.filterTargetKey);
1664
1729
  } catch (error) {
1665
1730
  return false;
@@ -2630,6 +2695,7 @@ class FlowSurfacesService {
2630
2695
  async dispatchPlanOnlyAction(action, payload, transaction, options = {}) {
2631
2696
  const actionOptions = {
2632
2697
  transaction,
2698
+ currentRoles: options.currentRoles,
2633
2699
  popupTemplateAliasSession: options.popupTemplateAliasSession,
2634
2700
  popupTemplateTreeCache: options.popupTemplateTreeCache,
2635
2701
  skipGeneratedLayoutSingleColumnErrors: options.skipGeneratedLayoutSingleColumnErrors === true
@@ -2788,6 +2854,22 @@ class FlowSurfacesService {
2788
2854
  getCollection: (dataSourceKey, collectionName) => this.getCollection(dataSourceKey || "main", collectionName || "")
2789
2855
  });
2790
2856
  }
2857
+ async prevalidateApplyBlueprintChartAssets(document, transaction) {
2858
+ var _a;
2859
+ const chartAssets = import_lodash.default.isPlainObject((_a = document.assets) == null ? void 0 : _a.charts) ? document.assets.charts : {};
2860
+ for (const [chartKey, chartAsset] of Object.entries(chartAssets)) {
2861
+ if (!import_lodash.default.isPlainObject(chartAsset)) {
2862
+ continue;
2863
+ }
2864
+ (0, import_service_utils.assertSupportedSimpleChanges)("chart", chartAsset, (0, import_configure_options.getConfigureOptionKeysForUse)("ChartBlockModel"));
2865
+ const nextConfigure = (0, import_chart_config.buildChartConfigureFromSemanticChanges)(void 0, chartAsset);
2866
+ await this.validateChartConfigureForRuntime(
2867
+ `applyBlueprint assets.charts.${chartKey}`,
2868
+ nextConfigure,
2869
+ transaction
2870
+ );
2871
+ }
2872
+ }
2791
2873
  getApplyBlueprintKanbanBlockResourceObject(block) {
2792
2874
  return import_lodash.default.isPlainObject(block == null ? void 0 : block.resource) ? block.resource : {};
2793
2875
  }
@@ -3176,25 +3258,48 @@ class FlowSurfacesService {
3176
3258
  }
3177
3259
  if (!options.transaction) {
3178
3260
  const createdKanbanSortFields = [];
3179
- try {
3180
- return await this.transaction(
3181
- (transaction) => this.applyBlueprintWithTransaction(
3182
- values,
3183
- {
3184
- ...options,
3185
- transaction
3186
- },
3187
- createdKanbanSortFields
3188
- )
3261
+ const mutationResult = await this.applyBlueprintMutationWithoutExternalTransaction(
3262
+ values,
3263
+ options,
3264
+ createdKanbanSortFields
3265
+ );
3266
+ const surface = await this.get(mutationResult.pageLocator, { currentRoles: options.currentRoles });
3267
+ return this.buildApplyBlueprintResponse(mutationResult.mode, mutationResult.pageLocator, surface);
3268
+ }
3269
+ }
3270
+ async applyBlueprintMutationWithoutExternalTransaction(values, options = {}, createdKanbanSortFields) {
3271
+ try {
3272
+ await this.assertApplyBlueprintAuthoringPayload(values, options);
3273
+ const document = (0, import_blueprint.prepareFlowSurfaceApplyBlueprintDocument)(values);
3274
+ await this.prevalidateApplyBlueprintChartAssets(document);
3275
+ if (document.mode === "create") {
3276
+ return await this.applyBlueprintWithTransaction(
3277
+ values,
3278
+ { ...options, skipAuthoringValidation: true },
3279
+ createdKanbanSortFields,
3280
+ {
3281
+ readSurface: false
3282
+ }
3189
3283
  );
3190
- } catch (error) {
3191
- await this.cleanupApplyBlueprintKanbanSortFields(createdKanbanSortFields);
3192
- throw error;
3193
3284
  }
3285
+ return await this.transaction(
3286
+ (transaction) => this.applyBlueprintWithTransaction(
3287
+ values,
3288
+ {
3289
+ ...options,
3290
+ transaction,
3291
+ skipAuthoringValidation: true
3292
+ },
3293
+ createdKanbanSortFields,
3294
+ { readSurface: false }
3295
+ )
3296
+ );
3297
+ } catch (error) {
3298
+ await this.cleanupApplyBlueprintKanbanSortFields(createdKanbanSortFields);
3299
+ throw error;
3194
3300
  }
3195
3301
  }
3196
- async applyBlueprintWithTransaction(values, options = {}, createdKanbanSortFields) {
3197
- var _a;
3302
+ async assertApplyBlueprintAuthoringPayload(values, options = {}) {
3198
3303
  const enabledPackages = await this.resolveEnabledPluginPackages(options);
3199
3304
  await (0, import_authoring_validation.assertFlowSurfaceAuthoringPayload)("applyBlueprint", values, {
3200
3305
  transaction: options.transaction,
@@ -3202,6 +3307,11 @@ class FlowSurfacesService {
3202
3307
  findMenuGroupRoutesByTitle: (title, transaction) => this.findMenuGroupRoutesByTitle(title, transaction),
3203
3308
  getCollection: (dataSourceKey, collectionName) => this.getCollection(dataSourceKey || "main", collectionName || "")
3204
3309
  });
3310
+ }
3311
+ async applyBlueprintWithTransaction(values, options = {}, createdKanbanSortFields, resultOptions = {}) {
3312
+ if (options.skipAuthoringValidation !== true) {
3313
+ await this.assertApplyBlueprintAuthoringPayload(values, options);
3314
+ }
3205
3315
  const prepared = await this.prepareApplyBlueprintRequest(values, options.transaction, createdKanbanSortFields);
3206
3316
  const popupTemplateAliasSession = this.createPopupTemplateAliasSession();
3207
3317
  const popupTemplateTreeCache = /* @__PURE__ */ new Map();
@@ -3214,6 +3324,7 @@ class FlowSurfacesService {
3214
3324
  }
3215
3325
  },
3216
3326
  this.buildPlanningRuntimeDeps({
3327
+ currentRoles: options.currentRoles,
3217
3328
  popupTemplateAliasSession,
3218
3329
  popupTemplateTreeCache,
3219
3330
  skipGeneratedLayoutSingleColumnErrors: true
@@ -3221,10 +3332,21 @@ class FlowSurfacesService {
3221
3332
  options
3222
3333
  );
3223
3334
  const pageLocator = (0, import_blueprint.resolveApplyBlueprintPageLocator)(prepared, result);
3335
+ if (resultOptions.readSurface === false) {
3336
+ return {
3337
+ version: "1",
3338
+ mode: prepared.document.mode,
3339
+ pageLocator
3340
+ };
3341
+ }
3224
3342
  const surface = await this.get(pageLocator, options);
3343
+ return this.buildApplyBlueprintResponse(prepared.document.mode, pageLocator, surface);
3344
+ }
3345
+ buildApplyBlueprintResponse(mode, pageLocator, surface) {
3346
+ var _a;
3225
3347
  return {
3226
3348
  version: "1",
3227
- mode: prepared.document.mode,
3349
+ mode,
3228
3350
  target: (0, import_service_utils.buildDefinedPayload)({
3229
3351
  pageSchemaUid: pageLocator.pageSchemaUid,
3230
3352
  pageUid: (_a = surface == null ? void 0 : surface.target) == null ? void 0 : _a.uid
@@ -4925,6 +5047,7 @@ class FlowSurfacesService {
4925
5047
  await this.applyInlineNodeSettings(actionName, targetUid, settings, runtimeOptions);
4926
5048
  },
4927
5049
  resolveBlockSettings: (settings, state, block) => this.resolveComposeBlockSettings(settings, state.keyMap, block),
5050
+ resolveActionSettings: (settings, state, block, action, actionName) => this.resolveComposeActionSettings(settings, state.keyMap, block, action, actionName),
4928
5051
  createField: async (payload) => this.addField(payload, {
4929
5052
  ...runtimeOptions,
4930
5053
  popupTemplateAliasSession
@@ -5021,11 +5144,16 @@ class FlowSurfacesService {
5021
5144
  const inheritedResourceInit = (currentResourceInit == null ? void 0 : currentResourceInit.collectionName) ? currentResourceInit : (_a = await this.locator.resolveCollectionContext(current == null ? void 0 : current.uid, options.transaction).catch(() => null)) == null ? void 0 : _a.resourceInit;
5022
5145
  const enabledPackages = await this.resolveEnabledPluginPackages(options);
5023
5146
  const popupDefaultsMetadata = options.skipConfigureGeneratedDefaultPopup ? void 0 : this.buildPopupDefaultsMetadata(values == null ? void 0 : values.defaults);
5147
+ const popupProfile = await this.resolvePopupBlockProfile(target.uid, resolved, current, options.transaction).catch(
5148
+ () => null
5149
+ );
5150
+ const popupAuthoringContext = import_lodash.default.isPlainObject(changes == null ? void 0 : changes.resource) && Object.prototype.hasOwnProperty.call(changes.resource, "binding") ? this.buildAuthoringContextFromPopupProfile(popupProfile) : {};
5024
5151
  await (0, import_authoring_validation.assertFlowSurfaceAuthoringPayload)("configure", values, {
5025
5152
  transaction: options.transaction,
5026
5153
  hostBlockType: current == null ? void 0 : current.use,
5027
5154
  hostDataSourceKey: inheritedResourceInit == null ? void 0 : inheritedResourceInit.dataSourceKey,
5028
5155
  hostCollectionName: inheritedResourceInit == null ? void 0 : inheritedResourceInit.collectionName,
5156
+ ...popupAuthoringContext,
5029
5157
  enabledPackages,
5030
5158
  getCollection: (dataSourceKey, collectionName) => this.getCollection(dataSourceKey || "main", collectionName || ""),
5031
5159
  currentNode: current,
@@ -5098,6 +5226,9 @@ class FlowSurfacesService {
5098
5226
  if ((current == null ? void 0 : current.use) === "CommentsBlockModel") {
5099
5227
  return this.configureCommentsBlock(target, changes, options);
5100
5228
  }
5229
+ if ((current == null ? void 0 : current.use) === "RecordHistoryBlockModel") {
5230
+ return this.configureRecordHistoryBlock(target, current, changes, options);
5231
+ }
5101
5232
  if ((current == null ? void 0 : current.use) === "TableActionsColumnModel") {
5102
5233
  return this.configureActionColumn(target, changes, options);
5103
5234
  }
@@ -5676,21 +5807,24 @@ class FlowSurfacesService {
5676
5807
  return nextGrid;
5677
5808
  }
5678
5809
  buildBlockCreateResult(tree, parentUid, subKey, popupSurface) {
5679
- var _a, _b, _c, _d, _e;
5810
+ var _a, _b, _c, _d, _e, _f;
5680
5811
  const gridNode = (0, import_service_utils.getSingleNodeSubModel)((_a = tree == null ? void 0 : tree.subModels) == null ? void 0 : _a.grid);
5681
5812
  const itemNode = (0, import_service_utils.getSingleNodeSubModel)((_b = tree == null ? void 0 : tree.subModels) == null ? void 0 : _b.item);
5682
- const itemGridNode = (0, import_service_utils.getSingleNodeSubModel)((_c = itemNode == null ? void 0 : itemNode.subModels) == null ? void 0 : _c.grid);
5683
- const columnNodes = (0, import_service_utils.getNodeSubModelList)((_d = tree == null ? void 0 : tree.subModels) == null ? void 0 : _d.columns);
5813
+ const commentItemNode = (0, import_service_utils.getNodeSubModelList)((_c = tree == null ? void 0 : tree.subModels) == null ? void 0 : _c.items).find(
5814
+ (item) => (item == null ? void 0 : item.use) === "CommentItemModel"
5815
+ );
5816
+ const itemGridNode = (0, import_service_utils.getSingleNodeSubModel)((_d = itemNode == null ? void 0 : itemNode.subModels) == null ? void 0 : _d.grid);
5817
+ const columnNodes = (0, import_service_utils.getNodeSubModelList)((_e = tree == null ? void 0 : tree.subModels) == null ? void 0 : _e.columns);
5684
5818
  const blockGridUid = (gridNode == null ? void 0 : gridNode.uid) || (itemGridNode == null ? void 0 : itemGridNode.uid);
5685
5819
  const popupGridUid = popupSurface == null ? void 0 : popupSurface.gridUid;
5686
- const actionsColumnUid = (_e = columnNodes.find((item) => item.use === "TableActionsColumnModel")) == null ? void 0 : _e.uid;
5820
+ const actionsColumnUid = (_f = columnNodes.find((item) => item.use === "TableActionsColumnModel")) == null ? void 0 : _f.uid;
5687
5821
  return {
5688
5822
  uid: tree.uid,
5689
5823
  parentUid,
5690
5824
  subKey,
5691
5825
  ...blockGridUid || popupGridUid ? { gridUid: blockGridUid || popupGridUid } : {},
5692
5826
  ...blockGridUid ? { blockGridUid } : {},
5693
- ...(itemNode == null ? void 0 : itemNode.uid) ? { itemUid: itemNode.uid } : {},
5827
+ ...(itemNode == null ? void 0 : itemNode.uid) || (commentItemNode == null ? void 0 : commentItemNode.uid) ? { itemUid: (itemNode == null ? void 0 : itemNode.uid) || commentItemNode.uid } : {},
5694
5828
  ...(itemGridNode == null ? void 0 : itemGridNode.uid) ? { itemGridUid: itemGridNode.uid } : {},
5695
5829
  ...actionsColumnUid ? { actionsColumnUid } : {},
5696
5830
  ...popupSurface ? {
@@ -6131,7 +6265,7 @@ class FlowSurfacesService {
6131
6265
  };
6132
6266
  }
6133
6267
  async addBlock(values, options = {}) {
6134
- var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k;
6268
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l;
6135
6269
  const enabledPackages = await this.resolveEnabledPluginPackages(options);
6136
6270
  const templateRef = import_lodash.default.isUndefined(values == null ? void 0 : values.template) || !(0, import_template_reference.hasFlowSurfaceTemplateReference)(values == null ? void 0 : values.template) ? void 0 : this.normalizeFlowTemplateReference("addBlock", values.template, {
6137
6271
  allowUsage: true,
@@ -6241,10 +6375,22 @@ class FlowSurfacesService {
6241
6375
  resourceInit: resolvedResourceInit,
6242
6376
  resourceField: rawResourceInit ? "resourceInit" : (semanticResource == null ? void 0 : semanticResource.kind) === "raw" ? "resource" : void 0
6243
6377
  });
6244
- const effectiveResourceInit = (catalogItem.use === "CalendarBlockModel" || catalogItem.use === "KanbanBlockModel") && resolvedResourceInit.collectionName && !resolvedResourceInit.dataSourceKey ? {
6378
+ let effectiveResourceInit = (catalogItem.use === "CalendarBlockModel" || catalogItem.use === "KanbanBlockModel") && resolvedResourceInit.collectionName && !resolvedResourceInit.dataSourceKey ? {
6245
6379
  ...resolvedResourceInit,
6246
6380
  dataSourceKey: "main"
6247
6381
  } : resolvedResourceInit;
6382
+ if (catalogItem.use === "RecordHistoryBlockModel") {
6383
+ const normalizedRecordHistoryCreate = this.normalizeRecordHistoryBlockCreateState({
6384
+ actionName: "addBlock",
6385
+ resourceInit: effectiveResourceInit,
6386
+ popupProfile,
6387
+ stepParams: values.stepParams
6388
+ });
6389
+ effectiveResourceInit = normalizedRecordHistoryCreate.resourceInit;
6390
+ values.stepParams = normalizedRecordHistoryCreate.stepParams;
6391
+ }
6392
+ this.assertInitialBlockResourceCompatible("addBlock", catalogItem.use, effectiveResourceInit, popupProfile);
6393
+ this.assertInitialBlockSettingsCompatible("addBlock", catalogItem.use, inlineSettings);
6248
6394
  const inlineFields = hasInlineFields ? this.normalizeComposeBlock(
6249
6395
  {
6250
6396
  key: String((values == null ? void 0 : values.key) || catalogItem.key || (values == null ? void 0 : values.type) || (values == null ? void 0 : values.use) || "addBlock_inline").trim() || "addBlock_inline",
@@ -6349,18 +6495,21 @@ class FlowSurfacesService {
6349
6495
  );
6350
6496
  const gridNode = (0, import_service_utils.getSingleNodeSubModel)((_b = tree.subModels) == null ? void 0 : _b.grid);
6351
6497
  const itemNode = (0, import_service_utils.getSingleNodeSubModel)((_c = tree.subModels) == null ? void 0 : _c.item);
6352
- const itemGridNode = (0, import_service_utils.getSingleNodeSubModel)((_d = itemNode == null ? void 0 : itemNode.subModels) == null ? void 0 : _d.grid);
6353
- const columnNodes = (0, import_service_utils.getNodeSubModelList)((_e = tree.subModels) == null ? void 0 : _e.columns);
6498
+ const commentItemNode = (0, import_service_utils.getNodeSubModelList)((_d = tree.subModels) == null ? void 0 : _d.items).find(
6499
+ (item) => (item == null ? void 0 : item.use) === "CommentItemModel"
6500
+ );
6501
+ const itemGridNode = (0, import_service_utils.getSingleNodeSubModel)((_e = itemNode == null ? void 0 : itemNode.subModels) == null ? void 0 : _e.grid);
6502
+ const columnNodes = (0, import_service_utils.getNodeSubModelList)((_f = tree.subModels) == null ? void 0 : _f.columns);
6354
6503
  const blockGridUid = (gridNode == null ? void 0 : gridNode.uid) || (itemGridNode == null ? void 0 : itemGridNode.uid);
6355
6504
  const popupGridUid = popupSurface == null ? void 0 : popupSurface.gridUid;
6356
- const actionsColumnUid = catalogItem.use === "TableBlockModel" ? await this.ensureTableActionsColumn(created, options.transaction) : (_f = columnNodes.find((item) => item.use === "TableActionsColumnModel")) == null ? void 0 : _f.uid;
6505
+ const actionsColumnUid = catalogItem.use === "TableBlockModel" ? await this.ensureTableActionsColumn(created, options.transaction) : (_g = columnNodes.find((item) => item.use === "TableActionsColumnModel")) == null ? void 0 : _g.uid;
6357
6506
  const result = {
6358
6507
  uid: created,
6359
6508
  parentUid,
6360
6509
  subKey,
6361
6510
  ...blockGridUid || popupGridUid ? { gridUid: blockGridUid || popupGridUid } : {},
6362
6511
  ...blockGridUid ? { blockGridUid } : {},
6363
- ...(itemNode == null ? void 0 : itemNode.uid) ? { itemUid: itemNode.uid } : {},
6512
+ ...(itemNode == null ? void 0 : itemNode.uid) || (commentItemNode == null ? void 0 : commentItemNode.uid) ? { itemUid: (itemNode == null ? void 0 : itemNode.uid) || commentItemNode.uid } : {},
6364
6513
  ...(itemGridNode == null ? void 0 : itemGridNode.uid) ? { itemGridUid: itemGridNode.uid } : {},
6365
6514
  ...actionsColumnUid ? { actionsColumnUid } : {},
6366
6515
  ...popupSurface ? {
@@ -6420,7 +6569,7 @@ class FlowSurfacesService {
6420
6569
  ) : catalogItem.use === "KanbanBlockModel" ? this.omitHiddenPopupSettingsForConfigure(inlineSettings, "kanban") : inlineSettings;
6421
6570
  await this.applyInlineNodeSettings("addBlock", created, inlineSettingsForConfigure, options);
6422
6571
  await ensureInitialBlockPopupHosts();
6423
- if ((_g = inlineFields == null ? void 0 : inlineFields.fields) == null ? void 0 : _g.length) {
6572
+ if ((_h = inlineFields == null ? void 0 : inlineFields.fields) == null ? void 0 : _h.length) {
6424
6573
  const fieldTargetUid = this.resolveComposeFieldContainerUid(inlineFields, result);
6425
6574
  const createdByKey = {};
6426
6575
  for (const fieldSpec of inlineFields.fields) {
@@ -6470,7 +6619,7 @@ class FlowSurfacesService {
6470
6619
  includeAsyncNode: true
6471
6620
  });
6472
6621
  const layoutItems = import_lodash.default.castArray(
6473
- ((_j = (_i = (_h = layoutHost == null ? void 0 : layoutHost.subModels) == null ? void 0 : _h.grid) == null ? void 0 : _i.subModels) == null ? void 0 : _j.items) || ((_k = layoutHost == null ? void 0 : layoutHost.subModels) == null ? void 0 : _k.items) || []
6622
+ ((_k = (_j = (_i = layoutHost == null ? void 0 : layoutHost.subModels) == null ? void 0 : _i.grid) == null ? void 0 : _j.subModels) == null ? void 0 : _k.items) || ((_l = layoutHost == null ? void 0 : layoutHost.subModels) == null ? void 0 : _l.items) || []
6474
6623
  );
6475
6624
  const layoutPayload = this.buildComposeLayoutPayload({
6476
6625
  layout: inlineFields.fieldsLayout,
@@ -6958,13 +7107,36 @@ class FlowSurfacesService {
6958
7107
  return result2;
6959
7108
  }
6960
7109
  const resourceContext = container.ownerUid ? await this.locator.resolveCollectionContext(container.ownerUid, options.transaction).catch(() => null) : null;
7110
+ const aiEmployeeSettingsPayload = this.isAIEmployeeActionUse(actionCatalogItem.use) ? await this.normalizeAIEmployeeActionPublicSettings("addAction", inlineSettings || {}, {
7111
+ transaction: options.transaction,
7112
+ enabledPackages,
7113
+ requireUsername: true,
7114
+ currentRoles: options.currentRoles,
7115
+ selfUid: container.ownerUid,
7116
+ promptContext: {
7117
+ kind: "container",
7118
+ ownerUid: container.ownerUid,
7119
+ scope: resolvedScope
7120
+ }
7121
+ }) : void 0;
7122
+ const actionSettingsPayload = {
7123
+ props: values.props,
7124
+ stepParams: values.stepParams
7125
+ };
7126
+ if (aiEmployeeSettingsPayload) {
7127
+ this.mergeAIEmployeeActionSettingsPayload(
7128
+ { use: actionCatalogItem.use },
7129
+ actionSettingsPayload,
7130
+ aiEmployeeSettingsPayload
7131
+ );
7132
+ }
6961
7133
  const action = (0, import_builder.buildActionTree)({
6962
7134
  use: actionCatalogItem.use,
6963
7135
  containerUse: container.ownerUse,
6964
7136
  resourceInit: values.resourceInit || (resourceContext == null ? void 0 : resourceContext.resourceInit),
6965
- props: values.props,
7137
+ props: actionSettingsPayload.props,
6966
7138
  decoratorProps: values.decoratorProps,
6967
- stepParams: values.stepParams,
7139
+ stepParams: actionSettingsPayload.stepParams,
6968
7140
  flowRegistry: values.flowRegistry
6969
7141
  });
6970
7142
  this.contractGuard.validateNodeTreeAgainstContract(action);
@@ -6977,7 +7149,9 @@ class FlowSurfacesService {
6977
7149
  },
6978
7150
  { transaction: options.transaction }
6979
7151
  );
6980
- await this.applyInlineNodeSettings("addAction", created, inlineSettings, options);
7152
+ if (!this.isAIEmployeeActionUse(actionCatalogItem.use)) {
7153
+ await this.applyInlineNodeSettings("addAction", created, inlineSettings, options);
7154
+ }
6981
7155
  await this.applyInlineActionPopup("addAction", created, inlinePopup, {
6982
7156
  ...options,
6983
7157
  enabledPackages,
@@ -7029,15 +7203,56 @@ class FlowSurfacesService {
7029
7203
  context: "addRecordAction"
7030
7204
  });
7031
7205
  const materializedContainer = await this.materializeRecordActionContainer(container, options.transaction);
7206
+ const reusableAction = await this.resolveReusableSingletonAction({
7207
+ parentUid: materializedContainer.parentUid,
7208
+ ownerUse: container.ownerUse,
7209
+ actionUse: actionCatalogItem.use,
7210
+ transaction: options.transaction
7211
+ });
7212
+ if (reusableAction == null ? void 0 : reusableAction.uid) {
7213
+ await this.applyInlineNodeSettings("addRecordAction", reusableAction.uid, inlineSettings, options);
7214
+ const result2 = {
7215
+ uid: reusableAction.uid,
7216
+ parentUid: materializedContainer.parentUid,
7217
+ subKey: materializedContainer.subKey,
7218
+ scope: actionCatalogItem.scope,
7219
+ ...await this.collectComposeActionKeys(reusableAction.uid, options.transaction)
7220
+ };
7221
+ await this.persistCreatedKeysForAction("addRecordAction", values, result2, options.transaction);
7222
+ return result2;
7223
+ }
7032
7224
  const resourceContext = container.ownerUid ? await this.locator.resolveCollectionContext(container.ownerUid, options.transaction).catch(() => null) : null;
7033
7225
  const resourceInit = this.isAddChildCatalogItem(actionCatalogItem) ? await this.resolveAddChildResourceInitForOwnerNode(container.ownerNode, options.transaction) : values.resourceInit || (resourceContext == null ? void 0 : resourceContext.resourceInit);
7226
+ const aiEmployeeSettingsPayload = this.isAIEmployeeActionUse(actionCatalogItem.use) ? await this.normalizeAIEmployeeActionPublicSettings("addRecordAction", inlineSettings || {}, {
7227
+ transaction: options.transaction,
7228
+ enabledPackages,
7229
+ requireUsername: true,
7230
+ currentRoles: options.currentRoles,
7231
+ selfUid: container.ownerUid,
7232
+ promptContext: {
7233
+ kind: "container",
7234
+ ownerUid: container.ownerUid,
7235
+ scope: resolvedScope
7236
+ }
7237
+ }) : void 0;
7238
+ const actionSettingsPayload = {
7239
+ props: values.props,
7240
+ stepParams: values.stepParams
7241
+ };
7242
+ if (aiEmployeeSettingsPayload) {
7243
+ this.mergeAIEmployeeActionSettingsPayload(
7244
+ { use: actionCatalogItem.use },
7245
+ actionSettingsPayload,
7246
+ aiEmployeeSettingsPayload
7247
+ );
7248
+ }
7034
7249
  const action = (0, import_builder.buildActionTree)({
7035
7250
  use: actionCatalogItem.use,
7036
7251
  containerUse: container.containerUse,
7037
7252
  resourceInit,
7038
- props: values.props,
7253
+ props: actionSettingsPayload.props,
7039
7254
  decoratorProps: values.decoratorProps,
7040
- stepParams: values.stepParams,
7255
+ stepParams: actionSettingsPayload.stepParams,
7041
7256
  flowRegistry: values.flowRegistry
7042
7257
  });
7043
7258
  this.contractGuard.validateNodeTreeAgainstContract(action);
@@ -7050,7 +7265,9 @@ class FlowSurfacesService {
7050
7265
  },
7051
7266
  { transaction: options.transaction }
7052
7267
  );
7053
- await this.applyInlineNodeSettings("addRecordAction", created, inlineSettings, options);
7268
+ if (!this.isAIEmployeeActionUse(actionCatalogItem.use)) {
7269
+ await this.applyInlineNodeSettings("addRecordAction", created, inlineSettings, options);
7270
+ }
7054
7271
  await this.applyInlineActionPopup("addRecordAction", created, inlinePopup, {
7055
7272
  ...options,
7056
7273
  enabledPackages,
@@ -7120,22 +7337,24 @@ class FlowSurfacesService {
7120
7337
  invoke: (itemValues, options) => this.addField(itemValues, options)
7121
7338
  });
7122
7339
  }
7123
- async addActions(values) {
7340
+ async addActions(values, options = {}) {
7124
7341
  return this.runBatchCreate({
7125
7342
  actionName: "addActions",
7126
7343
  values,
7127
7344
  itemField: "actions",
7128
7345
  resultField: "actions",
7129
- invoke: (itemValues, options) => this.addAction(itemValues, options)
7346
+ currentRoles: options.currentRoles,
7347
+ invoke: (itemValues, options2) => this.addAction(itemValues, options2)
7130
7348
  });
7131
7349
  }
7132
- async addRecordActions(values) {
7350
+ async addRecordActions(values, options = {}) {
7133
7351
  return this.runBatchCreate({
7134
7352
  actionName: "addRecordActions",
7135
7353
  values,
7136
7354
  itemField: "recordActions",
7137
7355
  resultField: "recordActions",
7138
- invoke: (itemValues, options) => this.addRecordAction(itemValues, options)
7356
+ currentRoles: options.currentRoles,
7357
+ invoke: (itemValues, options2) => this.addRecordAction(itemValues, options2)
7139
7358
  });
7140
7359
  }
7141
7360
  createPopupTemplateAliasSession() {
@@ -8943,6 +9162,16 @@ class FlowSurfacesService {
8943
9162
  };
8944
9163
  return resolvedSettings;
8945
9164
  }
9165
+ resolveComposeActionSettings(settings, keyMap, block, action, actionName) {
9166
+ var _a;
9167
+ if ((action == null ? void 0 : action.type) !== "aiEmployee") {
9168
+ return settings;
9169
+ }
9170
+ return this.normalizeAIEmployeeActionSettingsReferences(actionName, settings, {
9171
+ selfUid: (_a = block == null ? void 0 : block.result) == null ? void 0 : _a.uid,
9172
+ keyMap
9173
+ });
9174
+ }
8946
9175
  async applyInlineFieldPopup(actionName, result, popup, options) {
8947
9176
  popup = this.prepareInlinePopupTemplateAliases(actionName, popup, options.popupTemplateAliasSession);
8948
9177
  const fieldHostUid = result.fieldUid || result.uid;
@@ -10505,11 +10734,39 @@ class FlowSurfacesService {
10505
10734
  const target = await this.locator.resolve(writeTarget, options);
10506
10735
  const current = await this.loadResolvedNode(target, options.transaction);
10507
10736
  const normalizedValues = import_lodash.default.cloneDeep(values || {});
10737
+ if (this.isAIEmployeeActionUse(current == null ? void 0 : current.use) && !options.allowAIEmployeeInternalProps) {
10738
+ this.assertNoAIEmployeeInternalPropSettings("updateSettings", normalizedValues);
10739
+ }
10740
+ if (this.isAIEmployeeActionUse(current == null ? void 0 : current.use) && this.hasAIEmployeePublicSettings(normalizedValues)) {
10741
+ const enabledPackages = await this.resolveEnabledPluginPackages(options);
10742
+ const aiEmployeeSettingsPayload = await this.normalizeAIEmployeeActionPublicSettings(
10743
+ "updateSettings",
10744
+ import_lodash.default.pick(normalizedValues, AI_EMPLOYEE_PUBLIC_SETTING_KEYS),
10745
+ {
10746
+ transaction: options.transaction,
10747
+ enabledPackages,
10748
+ current,
10749
+ currentRoles: options.currentRoles,
10750
+ selfUid: await this.resolveAIEmployeeActionSelfUid(current, options.transaction),
10751
+ promptContext: {
10752
+ kind: "target",
10753
+ targetUid: (current == null ? void 0 : current.uid) || writeTarget.uid
10754
+ }
10755
+ }
10756
+ );
10757
+ AI_EMPLOYEE_PUBLIC_SETTING_KEYS.forEach((key) => {
10758
+ delete normalizedValues[key];
10759
+ });
10760
+ this.mergeAIEmployeeActionSettingsPayload(current, normalizedValues, aiEmployeeSettingsPayload);
10761
+ }
10508
10762
  assertNoFlowSurfaceIdTitleFieldSettings(normalizedValues, {
10509
10763
  action: "updateSettings",
10510
10764
  titleFieldErrorOptions: this.resolveRelationTitleFieldErrorOptionsForNode(current)
10511
10765
  });
10512
10766
  this.normalizeCanonicalBlockHeaderWriteForUpdateSettings(current, normalizedValues);
10767
+ if ((current == null ? void 0 : current.use) === "RecordHistoryBlockModel") {
10768
+ await this.assertRecordHistoryRecordIdWriteAllowed(current, normalizedValues, options.transaction);
10769
+ }
10513
10770
  const contract = (0, import_catalog.getNodeContract)(current.use);
10514
10771
  const nextPayload = { uid: current.uid };
10515
10772
  const shouldStripLegacyBlockHeader = import_lodash.default.has(normalizedValues, ["stepParams", "cardSettings", "titleDescription"]);
@@ -10542,6 +10799,20 @@ class FlowSurfacesService {
10542
10799
  nextPayload,
10543
10800
  options.replacePopupStepParamSubtrees === true
10544
10801
  );
10802
+ this.replaceRecordHistorySettingsForUpdateSettings(
10803
+ current,
10804
+ normalizedValues,
10805
+ nextPayload,
10806
+ options.replaceRecordHistorySettings === true
10807
+ );
10808
+ this.syncAIEmployeeTaskStepParamsForUpdateSettings(current, nextPayload);
10809
+ await this.normalizeAIEmployeeStepParamTasksForUpdateSettings(current, nextPayload, writeTarget, options);
10810
+ await this.assertAIEmployeeStepParamTaskPromptVariablesAllowedForUpdateSettings(
10811
+ current,
10812
+ nextPayload,
10813
+ writeTarget,
10814
+ options
10815
+ );
10545
10816
  this.syncCalendarPopupPropsForUpdateSettings(current, normalizedValues, nextPayload);
10546
10817
  this.syncKanbanPopupPropsForUpdateSettings(current, normalizedValues, nextPayload);
10547
10818
  this.syncDefaultSortingForUpdateSettings(current, normalizedValues, nextPayload);
@@ -10572,6 +10843,7 @@ class FlowSurfacesService {
10572
10843
  popupTemplateTreeCache: options.popupTemplateTreeCache
10573
10844
  }
10574
10845
  );
10846
+ this.validateBuilderChartFieldsForUpdateSettings(current, nextPayload);
10575
10847
  this.syncChartConfigureForUpdateSettings(current, nextPayload);
10576
10848
  await this.validateChartConfigureForUpdateSettings(current, nextPayload, options.transaction);
10577
10849
  this.syncCanonicalBlockHeaderForUpdateSettings(current, nextPayload);
@@ -10598,7 +10870,12 @@ class FlowSurfacesService {
10598
10870
  this.validateKanbanBlockState("updateSettings", effectiveNode);
10599
10871
  if (shouldValidateFlowRegistry && import_lodash.default.isPlainObject(effectiveNode.flowRegistry) && Object.keys(effectiveNode.flowRegistry).length) {
10600
10872
  this.contractGuard.validateFlowRegistry(effectiveNode, effectiveNode.flowRegistry);
10601
- this.assertFlowRegistryRunJsAuthoringPayload(effectiveNode.flowRegistry);
10873
+ await this.assertFlowRegistryRunJsAuthoringPayload(effectiveNode.flowRegistry, {
10874
+ current: effectiveNode,
10875
+ resolved: target,
10876
+ target: writeTarget,
10877
+ transaction: options.transaction
10878
+ });
10602
10879
  }
10603
10880
  if (Object.keys(nextPayload).length === 1) {
10604
10881
  return { uid: current.uid };
@@ -10683,6 +10960,27 @@ class FlowSurfacesService {
10683
10960
  import_lodash.default.set(stepParams, [groupKey, "dataScope", "filter"], import_lodash.default.cloneDeep(value.filter));
10684
10961
  });
10685
10962
  }
10963
+ async assertRecordHistoryRecordIdWriteAllowed(current, normalizedValues, transaction) {
10964
+ const recordIdPath = ["stepParams", "recordHistorySettings", "recordId", "recordId"];
10965
+ if ((current == null ? void 0 : current.use) !== "RecordHistoryBlockModel" || !import_lodash.default.has(normalizedValues, recordIdPath)) {
10966
+ return;
10967
+ }
10968
+ const recordId = import_lodash.default.get(normalizedValues, recordIdPath);
10969
+ if (import_lodash.default.isNil(recordId) || String(recordId).trim() === "") {
10970
+ return;
10971
+ }
10972
+ if (this.normalizeFlowContextTemplateValue(recordId) !== "{{ctx.view.inputArgs.filterByTk}}") {
10973
+ (0, import_errors.throwBadRequest)(
10974
+ `flowSurfaces updateSettings recordHistory recordId.recordId only supports the popup current record`
10975
+ );
10976
+ }
10977
+ const popupProfile = await this.resolvePopupBlockProfile(current.uid, void 0, void 0, transaction);
10978
+ if (!(popupProfile == null ? void 0 : popupProfile.isPopupSurface) || !popupProfile.hasCurrentRecord || popupProfile.scene !== "one") {
10979
+ (0, import_errors.throwBadRequest)(
10980
+ `flowSurfaces updateSettings recordHistory current-record history is only supported in one-record popup/details scenes`
10981
+ );
10982
+ }
10983
+ }
10686
10984
  syncCalendarPopupPropsForUpdateSettings(current, normalizedValues, nextPayload) {
10687
10985
  if ((current == null ? void 0 : current.use) !== "CalendarBlockModel" || !import_lodash.default.isPlainObject(normalizedValues == null ? void 0 : normalizedValues.props)) {
10688
10986
  return;
@@ -10739,6 +11037,14 @@ class FlowSurfacesService {
10739
11037
  nextPayload.stepParams = nextStepParams;
10740
11038
  }
10741
11039
  }
11040
+ replaceRecordHistorySettingsForUpdateSettings(current, normalizedValues, nextPayload, replaceRecordHistorySettings = false) {
11041
+ if (!replaceRecordHistorySettings || (current == null ? void 0 : current.use) !== "RecordHistoryBlockModel" || !import_lodash.default.has(normalizedValues, ["stepParams", "recordHistorySettings"])) {
11042
+ return;
11043
+ }
11044
+ const nextStepParams = import_lodash.default.cloneDeep(nextPayload.stepParams ?? (current == null ? void 0 : current.stepParams) ?? {});
11045
+ nextStepParams.recordHistorySettings = import_lodash.default.cloneDeep(normalizedValues.stepParams.recordHistorySettings || {});
11046
+ nextPayload.stepParams = nextStepParams;
11047
+ }
10742
11048
  normalizePopupStepParamReplacementForUpdateSettings(current, path, value, currentValue, replacePopupStepParamSubtrees = false) {
10743
11049
  if (!import_lodash.default.isPlainObject(value)) {
10744
11050
  return {};
@@ -11365,6 +11671,16 @@ class FlowSurfacesService {
11365
11671
  }
11366
11672
  import_lodash.default.set(nextPayload, ["stepParams", "chartSettings", "configure"], (0, import_chart_config.canonicalizeChartConfigure)(nextConfigure));
11367
11673
  }
11674
+ validateBuilderChartFieldsForUpdateSettings(current, nextPayload) {
11675
+ if ((current == null ? void 0 : current.use) !== "ChartBlockModel") {
11676
+ return;
11677
+ }
11678
+ const configure = import_lodash.default.get(nextPayload, ["stepParams", "chartSettings", "configure"]);
11679
+ if (!import_lodash.default.isPlainObject(configure)) {
11680
+ return;
11681
+ }
11682
+ this.validateBuilderChartFieldsForRuntime("updateSettings", configure);
11683
+ }
11368
11684
  async validateChartConfigureForUpdateSettings(current, nextPayload, transaction) {
11369
11685
  var _a, _b, _c;
11370
11686
  if ((current == null ? void 0 : current.use) !== "ChartBlockModel") {
@@ -11398,6 +11714,111 @@ class FlowSurfacesService {
11398
11714
  }
11399
11715
  }
11400
11716
  }
11717
+ normalizeChartSelectionFieldPath(input) {
11718
+ if (Array.isArray(input)) {
11719
+ return input.map((item) => String(item || "").trim()).filter(Boolean).join(".");
11720
+ }
11721
+ return String(input || "").trim();
11722
+ }
11723
+ validateBuilderChartFieldsForRuntime(actionName, configure) {
11724
+ var _a, _b;
11725
+ const resourceInit = (0, import_chart_config.getChartBuilderResourceInit)(configure);
11726
+ if (!(resourceInit == null ? void 0 : resourceInit.collectionName)) {
11727
+ return;
11728
+ }
11729
+ const dataSourceKey = resourceInit.dataSourceKey || "main";
11730
+ const collectionName = resourceInit.collectionName;
11731
+ const collection = this.getCollection(dataSourceKey, collectionName);
11732
+ if (!collection) {
11733
+ return;
11734
+ }
11735
+ const state = (0, import_chart_config.deriveChartSemanticState)(configure);
11736
+ if (((_a = state.query) == null ? void 0 : _a.mode) !== "builder") {
11737
+ return;
11738
+ }
11739
+ const selections = [
11740
+ ...import_lodash.default.castArray(state.query.measures || []).map((selection, index) => ({
11741
+ selection,
11742
+ path: `chart query.measures[${index}].field`
11743
+ })),
11744
+ ...import_lodash.default.castArray(state.query.dimensions || []).map((selection, index) => ({
11745
+ selection,
11746
+ path: `chart query.dimensions[${index}].field`
11747
+ }))
11748
+ ];
11749
+ for (const item of selections) {
11750
+ const fieldPath = this.normalizeChartSelectionFieldPath((_b = item.selection) == null ? void 0 : _b.field);
11751
+ if (!fieldPath) {
11752
+ continue;
11753
+ }
11754
+ const parsed = this.parseFieldPath(collection, fieldPath, void 0, dataSourceKey, collectionName);
11755
+ const field = (0, import_service_helpers.resolveFieldFromCollection)(parsed.leafCollection, parsed.leafFieldPath);
11756
+ if (!field) {
11757
+ if (this.collectionHasConcreteField(parsed.leafCollection, parsed.leafFieldPath)) {
11758
+ continue;
11759
+ }
11760
+ (0, import_errors.throwBadRequest)(
11761
+ `flowSurfaces ${actionName} ${item.path} '${fieldPath}' does not exist on collection '${dataSourceKey}.${collectionName}'`
11762
+ );
11763
+ }
11764
+ if (!fieldPath.includes(".") && (0, import_service_helpers.isAssociationField)(field)) {
11765
+ const suggestion = this.resolveBuilderChartAssociationSubfieldSuggestion(fieldPath, field, dataSourceKey);
11766
+ (0, import_errors.throwBadRequest)(
11767
+ `flowSurfaces ${actionName} ${item.path} '${fieldPath}' references an association field directly; use scalar subfield '${suggestion.suggestedFieldPath}' for builder charts`
11768
+ );
11769
+ }
11770
+ }
11771
+ }
11772
+ resolveBuilderChartAssociationSubfieldSuggestion(fieldPath, field, dataSourceKey) {
11773
+ try {
11774
+ const resolved = (0, import_association_title_field.resolveAssociationSafeTitleField)(
11775
+ field,
11776
+ dataSourceKey,
11777
+ (targetDataSourceKey, targetCollectionName) => this.getCollection(targetDataSourceKey, targetCollectionName),
11778
+ { fieldPath }
11779
+ );
11780
+ const titleField = String((resolved == null ? void 0 : resolved.fieldName) || "").trim();
11781
+ if (titleField) {
11782
+ return {
11783
+ suggestedFieldPath: `${fieldPath}.${titleField}`
11784
+ };
11785
+ }
11786
+ } catch {
11787
+ }
11788
+ return {
11789
+ suggestedFieldPath: `${fieldPath}.<field>`
11790
+ };
11791
+ }
11792
+ async validateChartConfigureForRuntime(actionName, configure, transaction) {
11793
+ var _a, _b, _c;
11794
+ if (!import_lodash.default.isPlainObject(configure)) {
11795
+ return;
11796
+ }
11797
+ this.validateBuilderChartFieldsForRuntime(actionName, configure);
11798
+ const state = (0, import_chart_config.deriveChartSemanticState)(configure);
11799
+ if (((_a = state.query) == null ? void 0 : _a.mode) !== "sql") {
11800
+ return;
11801
+ }
11802
+ const sqlPreview = await this.resolveSqlChartPreview(state.query, transaction);
11803
+ if (((_b = state.visual) == null ? void 0 : _b.mode) !== "basic") {
11804
+ return;
11805
+ }
11806
+ if (!((_c = sqlPreview.queryOutputs) == null ? void 0 : _c.length)) {
11807
+ (0, import_errors.throwBadRequest)(
11808
+ "chart visual.mode='basic' requires previewable SQL query outputs; write query first, then read flowSurfaces:context(path='chart'), or use visual.mode='custom' after browser verification"
11809
+ );
11810
+ }
11811
+ const supportedOutputs = new Set(
11812
+ sqlPreview.queryOutputs.map((output) => String((output == null ? void 0 : output.alias) || "").trim()).filter(Boolean)
11813
+ );
11814
+ for (const mappingField of (0, import_chart_config.getChartVisualMappingAliases)(state.visual)) {
11815
+ if (!supportedOutputs.has(mappingField)) {
11816
+ (0, import_errors.throwBadRequest)(
11817
+ `chart visual mappings only support SQL query output fields: ${Array.from(supportedOutputs).join(", ")}`
11818
+ );
11819
+ }
11820
+ }
11821
+ }
11401
11822
  stripChartSqlForInspection(sql) {
11402
11823
  return sql.replace(/\/\*[\s\S]*?\*\//g, " ").replace(/--[^\r\n]*/g, " ").replace(/'(?:''|[^'])*'/g, "''").replace(/"(?:[""]|[^"])*"/g, '""');
11403
11824
  }
@@ -11797,7 +12218,12 @@ class FlowSurfacesService {
11797
12218
  async persistEventFlowRegistry(actionName, target, current, flowRegistry, options = {}) {
11798
12219
  this.assertNoTreeConnectFieldsFlowRegistry(current, flowRegistry, actionName);
11799
12220
  this.contractGuard.validateFlowRegistry(current, flowRegistry);
11800
- this.assertFlowRegistryRunJsAuthoringPayload(flowRegistry);
12221
+ await this.assertFlowRegistryRunJsAuthoringPayload(flowRegistry, {
12222
+ current,
12223
+ resolved: target,
12224
+ target,
12225
+ transaction: options.transaction
12226
+ });
11801
12227
  if (target.kind === "tab" && target.tabRoute) {
11802
12228
  await this.routeSync.persistTabSettings(
11803
12229
  target,
@@ -11827,8 +12253,33 @@ class FlowSurfacesService {
11827
12253
  fingerprint: this.buildEventFlowFingerprint(flowRegistry)
11828
12254
  };
11829
12255
  }
11830
- assertFlowRegistryRunJsAuthoringPayload(flowRegistry) {
11831
- const errors = (0, import_runjs_authoring.collectFlowRegistryRunJsAuthoringErrors)(flowRegistry);
12256
+ async buildFlowRegistryRunJsAuthoringContext(input) {
12257
+ var _a, _b, _c, _d;
12258
+ const currentResourceInit = this.getDataBlockResourceInit(input.current);
12259
+ const inheritedResourceInit = (currentResourceInit == null ? void 0 : currentResourceInit.collectionName) ? currentResourceInit : ((_a = input.current) == null ? void 0 : _a.uid) ? (_b = await this.locator.resolveCollectionContext(input.current.uid, input.transaction).catch(() => null)) == null ? void 0 : _b.resourceInit : null;
12260
+ const resourceDataSourceKey = (inheritedResourceInit == null ? void 0 : inheritedResourceInit.dataSourceKey) || ((inheritedResourceInit == null ? void 0 : inheritedResourceInit.collectionName) ? "main" : void 0);
12261
+ const popupProfile = ((_c = input.target) == null ? void 0 : _c.uid) ? await this.resolvePopupBlockProfile(
12262
+ input.target.uid,
12263
+ input.resolved || input.target,
12264
+ input.current,
12265
+ input.transaction
12266
+ ).catch(() => null) : null;
12267
+ return (0, import_service_utils.buildDefinedPayload)({
12268
+ hostBlockType: (_d = input.current) == null ? void 0 : _d.use,
12269
+ hostDataSourceKey: resourceDataSourceKey,
12270
+ hostCollectionName: inheritedResourceInit == null ? void 0 : inheritedResourceInit.collectionName,
12271
+ currentDataSourceKey: resourceDataSourceKey,
12272
+ currentCollectionName: inheritedResourceInit == null ? void 0 : inheritedResourceInit.collectionName,
12273
+ ...this.buildAuthoringContextFromPopupProfile(popupProfile),
12274
+ currentNode: input.current
12275
+ });
12276
+ }
12277
+ async assertFlowRegistryRunJsAuthoringPayload(flowRegistry, context = {}) {
12278
+ const authoringContext = await this.buildFlowRegistryRunJsAuthoringContext(context);
12279
+ const errors = (0, import_runjs_authoring.collectFlowRegistryRunJsAuthoringErrors)(flowRegistry, "$.flowRegistry", {
12280
+ ...authoringContext,
12281
+ getCollection: (dataSourceKey, collectionName) => this.getCollection(dataSourceKey, collectionName)
12282
+ });
11832
12283
  if (errors.length) {
11833
12284
  (0, import_errors.throwAggregateBadRequest)(errors);
11834
12285
  }
@@ -12024,6 +12475,7 @@ class FlowSurfacesService {
12024
12475
  async dispatchOp(op, resolvedValues, ctx, runtimeOptions = {}) {
12025
12476
  const options = {
12026
12477
  transaction: ctx.transaction,
12478
+ currentRoles: runtimeOptions.currentRoles,
12027
12479
  popupTemplateAliasSession: runtimeOptions.popupTemplateAliasSession,
12028
12480
  popupTemplateTreeCache: runtimeOptions.popupTemplateTreeCache
12029
12481
  };
@@ -12582,7 +13034,7 @@ class FlowSurfacesService {
12582
13034
  const recordContainerUse = (0, import_service_utils.getCatalogRecordActionContainerUse)(blockUse);
12583
13035
  if (!recordContainerUse) {
12584
13036
  (0, import_errors.throwBadRequest)(
12585
- `flowSurfaces compose recordActions only support 'table', 'details', 'list' or 'gridCard' blocks`
13037
+ `flowSurfaces compose recordActions only support 'table', 'details', 'list', 'gridCard' or 'comments' blocks`
12586
13038
  );
12587
13039
  }
12588
13040
  const item = this.tryResolveActionCatalogItem(
@@ -13168,7 +13620,7 @@ class FlowSurfacesService {
13168
13620
  return filteredItems.filter((item) => !this.isAddChildCatalogItem(item));
13169
13621
  }
13170
13622
  async inspectRecordActionContainer(target, transaction) {
13171
- var _a, _b;
13623
+ var _a, _b, _c, _d;
13172
13624
  const resolved = await this.locator.resolve(target, { transaction });
13173
13625
  const node = resolved.node || await this.repository.findModelById(resolved.uid, { transaction, includeAsyncNode: true });
13174
13626
  const use = node == null ? void 0 : node.use;
@@ -13211,19 +13663,37 @@ class FlowSurfacesService {
13211
13663
  subType: "array"
13212
13664
  };
13213
13665
  }
13214
- if (use === "KanbanBlockModel") {
13215
- (0, import_errors.throwBadRequest)(
13216
- `flowSurfaces addRecordAction target '${use}' is not supported; kanban record actions are not exposed in the public API v1`
13217
- );
13218
- }
13219
- if (use === "TableActionsColumnModel") {
13220
- (0, import_errors.throwBadRequest)(
13221
- `flowSurfaces addRecordAction target '${use}' is an internal record action container; pass the owning table block uid instead`
13222
- );
13666
+ if (use === "CommentsBlockModel") {
13667
+ const itemUid = (_d = import_lodash.default.castArray(((_c = node.subModels) == null ? void 0 : _c.items) || [])[0]) == null ? void 0 : _d.uid;
13668
+ if (!itemUid) {
13669
+ (0, import_errors.throwConflict)(
13670
+ `flowSurfaces addRecordAction target '${use}' is missing its comment item subtree`,
13671
+ "FLOW_SURFACE_RECORD_ACTION_ITEM_SUBTREE_MISSING"
13672
+ );
13673
+ }
13674
+ return {
13675
+ ownerNode: node,
13676
+ ownerUid: node.uid,
13677
+ ownerUse: use,
13678
+ containerUse: "CommentItemModel",
13679
+ parentUid: itemUid,
13680
+ subKey: "actions",
13681
+ subType: "array"
13682
+ };
13683
+ }
13684
+ if (use === "KanbanBlockModel") {
13685
+ (0, import_errors.throwBadRequest)(
13686
+ `flowSurfaces addRecordAction target '${use}' is not supported; kanban record actions are not exposed in the public API v1`
13687
+ );
13688
+ }
13689
+ if (use === "TableActionsColumnModel") {
13690
+ (0, import_errors.throwBadRequest)(
13691
+ `flowSurfaces addRecordAction target '${use}' is an internal record action container; pass the owning table block uid instead`
13692
+ );
13223
13693
  }
13224
- if (use === "ListItemModel" || use === "GridCardItemModel") {
13694
+ if (use === "ListItemModel" || use === "GridCardItemModel" || use === "CommentItemModel") {
13225
13695
  (0, import_errors.throwBadRequest)(
13226
- `flowSurfaces addRecordAction target '${use}' is an internal record action container; pass the owning ${use === "ListItemModel" ? "list" : "gridCard"} block uid instead`
13696
+ `flowSurfaces addRecordAction target '${use}' is an internal record action container; pass the owning ${use === "ListItemModel" ? "list" : use === "GridCardItemModel" ? "gridCard" : "comments"} block uid instead`
13227
13697
  );
13228
13698
  }
13229
13699
  (0, import_errors.throwBadRequest)(
@@ -13277,6 +13747,7 @@ class FlowSurfacesService {
13277
13747
  result.result = await this.transaction(
13278
13748
  (transaction) => options.invoke(itemValues, {
13279
13749
  transaction,
13750
+ currentRoles: options.currentRoles,
13280
13751
  enabledPackages
13281
13752
  })
13282
13753
  );
@@ -13497,17 +13968,35 @@ class FlowSurfacesService {
13497
13968
  }
13498
13969
  }
13499
13970
  async resolveReusableSingletonAction(input) {
13500
- var _a;
13501
- if (!AUTO_SUBMIT_FORM_BLOCK_USES.has(input.ownerUse || "") || input.actionUse !== "FormSubmitActionModel") {
13502
- return null;
13971
+ var _a, _b, _c;
13972
+ if (AUTO_SUBMIT_FORM_BLOCK_USES.has(input.ownerUse || "") && input.actionUse === "FormSubmitActionModel") {
13973
+ const parentNode = await this.repository.findModelById(input.parentUid, {
13974
+ transaction: input.transaction,
13975
+ includeAsyncNode: true
13976
+ });
13977
+ return import_lodash.default.castArray(((_a = parentNode == null ? void 0 : parentNode.subModels) == null ? void 0 : _a.actions) || []).find(
13978
+ (action) => (action == null ? void 0 : action.use) === "FormSubmitActionModel" && (action == null ? void 0 : action.uid)
13979
+ ) || null;
13503
13980
  }
13504
- const parentNode = await this.repository.findModelById(input.parentUid, {
13505
- transaction: input.transaction,
13506
- includeAsyncNode: true
13507
- });
13508
- return import_lodash.default.castArray(((_a = parentNode == null ? void 0 : parentNode.subModels) == null ? void 0 : _a.actions) || []).find(
13509
- (action) => (action == null ? void 0 : action.use) === "FormSubmitActionModel" && (action == null ? void 0 : action.uid)
13510
- ) || null;
13981
+ if (input.ownerUse === "CommentsBlockModel" && COMMENT_ACTION_SINGLETON_USES.has(input.actionUse || "")) {
13982
+ const parentNode = await this.repository.findModelById(input.parentUid, {
13983
+ transaction: input.transaction,
13984
+ includeAsyncNode: true
13985
+ });
13986
+ return import_lodash.default.castArray(((_b = parentNode == null ? void 0 : parentNode.subModels) == null ? void 0 : _b.actions) || []).find(
13987
+ (action) => (action == null ? void 0 : action.use) === input.actionUse && (action == null ? void 0 : action.uid)
13988
+ ) || null;
13989
+ }
13990
+ if (input.ownerUse === "RecordHistoryBlockModel" && RECORD_HISTORY_ACTION_SINGLETON_USES.has(input.actionUse || "")) {
13991
+ const parentNode = await this.repository.findModelById(input.parentUid, {
13992
+ transaction: input.transaction,
13993
+ includeAsyncNode: true
13994
+ });
13995
+ return import_lodash.default.castArray(((_c = parentNode == null ? void 0 : parentNode.subModels) == null ? void 0 : _c.actions) || []).find(
13996
+ (action) => (action == null ? void 0 : action.use) === input.actionUse && (action == null ? void 0 : action.uid)
13997
+ ) || null;
13998
+ }
13999
+ return null;
13511
14000
  }
13512
14001
  normalizeComposeBlock(input, index, enabledPackages, preserveSingleScopeDataBlockTitle = false, popupDefaultsMetadata, resourceFallback) {
13513
14002
  if (!import_lodash.default.isPlainObject(input)) {
@@ -13729,6 +14218,7 @@ class FlowSurfacesService {
13729
14218
  return blockResult.uid;
13730
14219
  }
13731
14220
  async resolveComposeRecordActionContainerUid(blockSpec, blockResult, transaction) {
14221
+ var _a, _b, _c;
13732
14222
  if (blockSpec.type === "table") {
13733
14223
  return this.ensureTableActionsColumn(blockResult.uid, transaction);
13734
14224
  }
@@ -13737,9 +14227,19 @@ class FlowSurfacesService {
13737
14227
  }
13738
14228
  if (!RECORD_ACTION_COMPOSE_BLOCK_TYPES.has(blockSpec.type)) {
13739
14229
  (0, import_errors.throwBadRequest)(
13740
- `flowSurfaces compose recordActions only support 'table', 'details', 'list' or 'gridCard' blocks`
14230
+ `flowSurfaces compose recordActions only support 'table', 'details', 'list', 'gridCard' or 'comments' blocks`
13741
14231
  );
13742
14232
  }
14233
+ if (blockSpec.type === "comments") {
14234
+ const itemUid = ((_c = import_lodash.default.castArray(((_b = (_a = blockResult == null ? void 0 : blockResult.tree) == null ? void 0 : _a.subModels) == null ? void 0 : _b.items) || [])[0]) == null ? void 0 : _c.uid) || blockResult.itemUid;
14235
+ if (!itemUid) {
14236
+ (0, import_errors.throwConflict)(
14237
+ `flowSurfaces compose block '${blockSpec.key}' is missing its comment item subtree`,
14238
+ "FLOW_SURFACE_COMPOSE_ITEM_SUBTREE_MISSING"
14239
+ );
14240
+ }
14241
+ return itemUid;
14242
+ }
13743
14243
  if (!blockResult.itemUid) {
13744
14244
  (0, import_errors.throwConflict)(
13745
14245
  `flowSurfaces compose block '${blockSpec.key}' is missing its item subtree`,
@@ -13752,7 +14252,7 @@ class FlowSurfacesService {
13752
14252
  const recordContainerUse = (0, import_service_utils.getCatalogRecordActionContainerUse)(blockUse);
13753
14253
  if (recordActions.length && !recordContainerUse) {
13754
14254
  (0, import_errors.throwBadRequest)(
13755
- `flowSurfaces compose recordActions only support 'table', 'details', 'list' or 'gridCard' blocks`
14255
+ `flowSurfaces compose recordActions only support 'table', 'details', 'list', 'gridCard' or 'comments' blocks`
13756
14256
  );
13757
14257
  }
13758
14258
  actions.forEach((action) => {
@@ -15117,10 +15617,212 @@ class FlowSurfacesService {
15117
15617
  options
15118
15618
  );
15119
15619
  }
15620
+ normalizeBlockResourceForValidation(resourceInit) {
15621
+ const init = (0, import_service_utils.normalizeSimpleResourceInit)(resourceInit || {}) || {};
15622
+ if (init.collectionName && !init.dataSourceKey) {
15623
+ init.dataSourceKey = "main";
15624
+ }
15625
+ return init;
15626
+ }
15627
+ isCommentTemplateCollection(collection) {
15628
+ var _a;
15629
+ return (collection == null ? void 0 : collection.template) === "comment" || ((_a = collection == null ? void 0 : collection.options) == null ? void 0 : _a.template) === "comment";
15630
+ }
15631
+ isCommentsAssociationField(field, targetCollection) {
15632
+ const fieldType = String((0, import_service_helpers.getFieldType)(field) || "").trim().toLowerCase();
15633
+ return (fieldType === "hasmany" || fieldType === "belongstomany") && this.isCommentTemplateCollection(targetCollection);
15634
+ }
15635
+ getRecordHistoryDeclaredFilterTargetKey(collection) {
15636
+ var _a, _b;
15637
+ const raw = Array.isArray(collection == null ? void 0 : collection.filterTargetKey) ? collection.filterTargetKey[0] : !import_lodash.default.isUndefined(collection == null ? void 0 : collection.filterTargetKey) ? collection.filterTargetKey : Array.isArray((_a = collection == null ? void 0 : collection.options) == null ? void 0 : _a.filterTargetKey) ? collection.options.filterTargetKey[0] : (_b = collection == null ? void 0 : collection.options) == null ? void 0 : _b.filterTargetKey;
15638
+ return String(raw || "").trim();
15639
+ }
15640
+ collectionHasConcreteField(collection, fieldName) {
15641
+ var _a, _b, _c, _d, _e, _f;
15642
+ const normalized = String(fieldName || "").trim();
15643
+ if (!normalized) {
15644
+ return false;
15645
+ }
15646
+ const modelAttributes = (typeof ((_a = collection == null ? void 0 : collection.model) == null ? void 0 : _a.getAttributes) === "function" ? collection.model.getAttributes() : null) || ((_b = collection == null ? void 0 : collection.model) == null ? void 0 : _b.rawAttributes) || ((_c = collection == null ? void 0 : collection.model) == null ? void 0 : _c.attributes) || {};
15647
+ const primaryKeyAttributes = import_lodash.default.castArray(
15648
+ ((_d = collection == null ? void 0 : collection.model) == null ? void 0 : _d.primaryKeyAttributes) || ((_e = collection == null ? void 0 : collection.model) == null ? void 0 : _e.primaryKeyAttribute) || []
15649
+ );
15650
+ const modelAttribute = modelAttributes == null ? void 0 : modelAttributes[normalized];
15651
+ const isModelPrimaryKey = primaryKeyAttributes.includes(normalized) || !!(modelAttribute == null ? void 0 : modelAttribute.primaryKey);
15652
+ return !!((0, import_service_helpers.resolveFieldFromCollection)(collection, normalized) || ((_f = collection == null ? void 0 : collection.getField) == null ? void 0 : _f.call(collection, normalized)) || (0, import_service_helpers.getCollectionFields)(collection).some((field) => (0, import_service_helpers.getFieldName)(field) === normalized) || isModelPrimaryKey);
15653
+ }
15654
+ assertInitialBlockResourceCompatible(actionName, blockUse, resourceInit, popupProfile) {
15655
+ if (blockUse === "CommentsBlockModel") {
15656
+ this.assertCommentsBlockResourceCompatible(actionName, resourceInit, popupProfile);
15657
+ }
15658
+ if (blockUse === "RecordHistoryBlockModel") {
15659
+ this.assertRecordHistoryBlockResourceCompatible(actionName, resourceInit, popupProfile);
15660
+ }
15661
+ }
15662
+ assertInitialBlockSettingsCompatible(actionName, blockUse, settings) {
15663
+ if (blockUse === "CommentsBlockModel") {
15664
+ this.assertCommentsSettingValues(actionName, settings);
15665
+ }
15666
+ if (blockUse === "RecordHistoryBlockModel") {
15667
+ this.assertRecordHistorySettingValues(actionName, settings);
15668
+ }
15669
+ }
15670
+ assertCommentsBlockResourceCompatible(actionName, resourceInit, popupProfile) {
15671
+ const init = this.normalizeBlockResourceForValidation(resourceInit);
15672
+ const collectionName = String(init.collectionName || "").trim();
15673
+ const dataSourceKey = String(init.dataSourceKey || "main").trim() || "main";
15674
+ if (!collectionName) {
15675
+ return;
15676
+ }
15677
+ const collection = this.getCollection(dataSourceKey, collectionName);
15678
+ if (!collection || !this.isCommentTemplateCollection(collection)) {
15679
+ (0, import_errors.throwBadRequest)(
15680
+ `flowSurfaces ${actionName} comments block requires a comment template collection; '${dataSourceKey}.${collectionName}' is not a comment template collection`
15681
+ );
15682
+ }
15683
+ const hasAssociationResource = (0, import_service_helpers.hasConfiguredFlowContextValue)(init.associationName) || (0, import_service_helpers.hasConfiguredFlowContextValue)(init.sourceId);
15684
+ if (popupProfile == null ? void 0 : popupProfile.isPopupSurface) {
15685
+ if (!hasAssociationResource || (0, import_service_helpers.hasConfiguredFlowContextValue)(init.filterByTk)) {
15686
+ (0, import_errors.throwBadRequest)(
15687
+ `flowSurfaces ${actionName} comments block in popups only supports resource.binding='associatedRecords'`
15688
+ );
15689
+ }
15690
+ return;
15691
+ }
15692
+ if (hasAssociationResource || (0, import_service_helpers.hasConfiguredFlowContextValue)(init.associationPathName) || (0, import_service_helpers.hasConfiguredFlowContextValue)(init.filterByTk)) {
15693
+ (0, import_errors.throwBadRequest)(
15694
+ `flowSurfaces ${actionName} comments block outside popups only supports a direct comment template collection resource`
15695
+ );
15696
+ }
15697
+ }
15698
+ assertRecordHistoryBlockResourceCompatible(actionName, resourceInit, popupProfile) {
15699
+ const init = this.normalizeBlockResourceForValidation(resourceInit);
15700
+ const collectionName = String(init.collectionName || "").trim();
15701
+ const dataSourceKey = String(init.dataSourceKey || "main").trim() || "main";
15702
+ if (!collectionName) {
15703
+ return;
15704
+ }
15705
+ if (RECORD_HISTORY_INTERNAL_COLLECTIONS.has(collectionName)) {
15706
+ (0, import_errors.throwBadRequest)(
15707
+ `flowSurfaces ${actionName} recordHistory block does not support internal collection '${collectionName}'`
15708
+ );
15709
+ }
15710
+ if ((0, import_service_helpers.hasConfiguredFlowContextValue)(init.associationName) || (0, import_service_helpers.hasConfiguredFlowContextValue)(init.associationPathName) || (0, import_service_helpers.hasConfiguredFlowContextValue)(init.sourceId)) {
15711
+ (0, import_errors.throwBadRequest)(
15712
+ `flowSurfaces ${actionName} recordHistory block does not support association resources; use a collection resource or resource.binding='currentRecord' in a one-record popup`
15713
+ );
15714
+ }
15715
+ if ((0, import_service_helpers.hasConfiguredFlowContextValue)(init.filterByTk)) {
15716
+ if (!(popupProfile == null ? void 0 : popupProfile.isPopupSurface) || !popupProfile.hasCurrentRecord || popupProfile.scene !== "one") {
15717
+ (0, import_errors.throwBadRequest)(
15718
+ `flowSurfaces ${actionName} recordHistory current-record history is only supported in one-record popup/details scenes`
15719
+ );
15720
+ }
15721
+ }
15722
+ const collection = this.getCollection(dataSourceKey, collectionName);
15723
+ if (!collection) {
15724
+ (0, import_errors.throwBadRequest)(
15725
+ `flowSurfaces ${actionName} recordHistory collection '${dataSourceKey}.${collectionName}' not found`
15726
+ );
15727
+ }
15728
+ const filterTargetKey = this.getRecordHistoryDeclaredFilterTargetKey(collection);
15729
+ if (!filterTargetKey || !this.collectionHasConcreteField(collection, filterTargetKey)) {
15730
+ (0, import_errors.throwBadRequest)(
15731
+ `flowSurfaces ${actionName} recordHistory block requires a real filterTargetKey on collection '${dataSourceKey}.${collectionName}'`
15732
+ );
15733
+ }
15734
+ }
15735
+ normalizeRecordHistoryBlockCreateState(input) {
15736
+ var _a;
15737
+ const init = this.normalizeBlockResourceForValidation(input.resourceInit);
15738
+ if (!(0, import_service_helpers.hasConfiguredFlowContextValue)(init.filterByTk)) {
15739
+ return {
15740
+ resourceInit: init,
15741
+ stepParams: input.stepParams
15742
+ };
15743
+ }
15744
+ if (!((_a = input.popupProfile) == null ? void 0 : _a.isPopupSurface) || !input.popupProfile.hasCurrentRecord || input.popupProfile.scene !== "one") {
15745
+ (0, import_errors.throwBadRequest)(
15746
+ `flowSurfaces ${input.actionName} recordHistory current-record history is only supported in one-record popup/details scenes`
15747
+ );
15748
+ }
15749
+ const nextResourceInit = import_lodash.default.omit(init, ["filterByTk", "associationName", "associationPathName", "sourceId"]);
15750
+ const nextStepParams = import_lodash.default.merge({}, import_lodash.default.cloneDeep(input.stepParams || {}), {
15751
+ recordHistorySettings: {
15752
+ recordId: {
15753
+ recordId: "{{ctx.view.inputArgs.filterByTk}}"
15754
+ }
15755
+ }
15756
+ });
15757
+ return {
15758
+ resourceInit: nextResourceInit,
15759
+ stepParams: nextStepParams
15760
+ };
15761
+ }
15762
+ async normalizeConfigureCollectionBlockResource(input) {
15763
+ const popupProfile = await this.resolvePopupBlockProfile(input.target.uid, void 0, void 0, input.transaction);
15764
+ const normalizedResource = this.normalizeResourceInput(input.resource);
15765
+ const resourceInit = await this.resolvePopupCollectionBlockResourceInit({
15766
+ actionName: input.actionName,
15767
+ blockUse: input.blockUse,
15768
+ popupProfile,
15769
+ semanticResource: (normalizedResource == null ? void 0 : normalizedResource.kind) === "semantic" ? normalizedResource.value : void 0,
15770
+ resourceInit: (normalizedResource == null ? void 0 : normalizedResource.kind) === "raw" ? normalizedResource.value : void 0
15771
+ });
15772
+ return {
15773
+ popupProfile,
15774
+ resourceInit
15775
+ };
15776
+ }
15777
+ assertCommentsSettingValues(actionName, settings) {
15778
+ if (!import_lodash.default.isPlainObject(settings) || !(0, import_service_utils.hasOwnDefined)(settings, "pageSize")) {
15779
+ return;
15780
+ }
15781
+ if (!COMMENTS_PAGE_SIZE_VALUES.has(Number(settings.pageSize))) {
15782
+ (0, import_errors.throwBadRequest)(
15783
+ `flowSurfaces ${actionName} comments pageSize must be one of ${Array.from(COMMENTS_PAGE_SIZE_VALUES).join(
15784
+ ", "
15785
+ )}`
15786
+ );
15787
+ }
15788
+ }
15789
+ assertRecordHistorySettingValues(actionName, settings) {
15790
+ var _a;
15791
+ if (!import_lodash.default.isPlainObject(settings)) {
15792
+ return;
15793
+ }
15794
+ if ((0, import_service_utils.hasOwnDefined)(settings, "sortOrder")) {
15795
+ const order = String(((_a = settings.sortOrder) == null ? void 0 : _a.order) || "").trim();
15796
+ if (!import_lodash.default.isPlainObject(settings.sortOrder) || order !== "asc" && order !== "desc") {
15797
+ (0, import_errors.throwBadRequest)(`flowSurfaces ${actionName} recordHistory sortOrder.order must be 'asc' or 'desc'`);
15798
+ }
15799
+ }
15800
+ if ((0, import_service_utils.hasOwnDefined)(settings, "expand")) {
15801
+ if (!import_lodash.default.isPlainObject(settings.expand) || typeof settings.expand.expand !== "boolean") {
15802
+ (0, import_errors.throwBadRequest)(`flowSurfaces ${actionName} recordHistory expand.expand must be a boolean`);
15803
+ }
15804
+ }
15805
+ if ((0, import_service_utils.hasOwnDefined)(settings, "template")) {
15806
+ if (!import_lodash.default.isPlainObject(settings.template) || settings.template.apply !== "current") {
15807
+ (0, import_errors.throwBadRequest)(`flowSurfaces ${actionName} recordHistory template only supports apply='current'`);
15808
+ }
15809
+ }
15810
+ }
15120
15811
  async configureCommentsBlock(target, changes, options) {
15121
15812
  const allowedKeys = (0, import_configure_options.getConfigureOptionKeysForUse)("CommentsBlockModel");
15122
15813
  const cardSettings = (0, import_service_utils.buildBlockTitleDescriptionFromSemanticChanges)(changes);
15123
15814
  (0, import_service_utils.assertSupportedSimpleChanges)("comments", changes, allowedKeys);
15815
+ this.assertCommentsSettingValues("configure", changes);
15816
+ const resourceChange = changes.resource ? await this.normalizeConfigureCollectionBlockResource({
15817
+ actionName: "configure",
15818
+ blockUse: "CommentsBlockModel",
15819
+ target,
15820
+ resource: changes.resource,
15821
+ transaction: options.transaction
15822
+ }) : void 0;
15823
+ if (resourceChange) {
15824
+ this.assertCommentsBlockResourceCompatible("configure", resourceChange.resourceInit, resourceChange.popupProfile);
15825
+ }
15124
15826
  return this.updateSettings(
15125
15827
  {
15126
15828
  target,
@@ -15128,7 +15830,7 @@ class FlowSurfacesService {
15128
15830
  ...cardSettings ? { cardSettings } : {},
15129
15831
  ...changes.resource ? {
15130
15832
  resourceSettings: {
15131
- init: (0, import_service_utils.normalizeSimpleResourceInit)(changes.resource)
15833
+ init: resourceChange == null ? void 0 : resourceChange.resourceInit
15132
15834
  }
15133
15835
  } : {},
15134
15836
  ...(0, import_service_utils.hasDefinedValue)(changes, ["pageSize", "dataScope"]) ? {
@@ -15142,6 +15844,67 @@ class FlowSurfacesService {
15142
15844
  options
15143
15845
  );
15144
15846
  }
15847
+ async configureRecordHistoryBlock(target, current, changes, options) {
15848
+ var _a, _b, _c;
15849
+ const allowedKeys = (0, import_configure_options.getConfigureOptionKeysForUse)("RecordHistoryBlockModel");
15850
+ const cardSettings = (0, import_service_utils.buildBlockTitleDescriptionFromSemanticChanges)(changes);
15851
+ (0, import_service_utils.assertSupportedSimpleChanges)("recordHistory", changes, allowedKeys);
15852
+ this.assertRecordHistorySettingValues("configure", changes);
15853
+ const resourceChange = changes.resource ? await this.normalizeConfigureCollectionBlockResource({
15854
+ actionName: "configure",
15855
+ blockUse: "RecordHistoryBlockModel",
15856
+ target,
15857
+ resource: changes.resource,
15858
+ transaction: options.transaction
15859
+ }) : void 0;
15860
+ const normalizedRecordHistoryResourceChange = resourceChange ? this.normalizeRecordHistoryBlockCreateState({
15861
+ actionName: "configure",
15862
+ resourceInit: resourceChange.resourceInit,
15863
+ popupProfile: resourceChange.popupProfile
15864
+ }) : void 0;
15865
+ if (resourceChange) {
15866
+ this.assertRecordHistoryBlockResourceCompatible(
15867
+ "configure",
15868
+ normalizedRecordHistoryResourceChange == null ? void 0 : normalizedRecordHistoryResourceChange.resourceInit,
15869
+ resourceChange.popupProfile
15870
+ );
15871
+ }
15872
+ const recordHistorySettingChanges = (0, import_service_utils.buildDefinedPayload)({
15873
+ ...(0, import_service_utils.hasOwnDefined)(changes, "sortOrder") ? { sortOrder: { order: changes.sortOrder.order } } : {},
15874
+ ...(0, import_service_utils.hasOwnDefined)(changes, "dataScope") ? { dataScope: { filter: changes.dataScope } } : {},
15875
+ ...(0, import_service_utils.hasOwnDefined)(changes, "expand") ? { expand: { expand: changes.expand.expand } } : {},
15876
+ ...(0, import_service_utils.hasOwnDefined)(changes, "template") ? { template: { apply: "current" } } : {}
15877
+ });
15878
+ const recordHistorySettings = resourceChange ? import_lodash.default.merge(
15879
+ {},
15880
+ import_lodash.default.cloneDeep(((_a = current == null ? void 0 : current.stepParams) == null ? void 0 : _a.recordHistorySettings) || {}),
15881
+ ((_b = normalizedRecordHistoryResourceChange == null ? void 0 : normalizedRecordHistoryResourceChange.stepParams) == null ? void 0 : _b.recordHistorySettings) || {},
15882
+ recordHistorySettingChanges
15883
+ ) : Object.keys(recordHistorySettingChanges).length ? recordHistorySettingChanges : void 0;
15884
+ if (resourceChange && !((_c = normalizedRecordHistoryResourceChange == null ? void 0 : normalizedRecordHistoryResourceChange.stepParams) == null ? void 0 : _c.recordHistorySettings)) {
15885
+ import_lodash.default.unset(recordHistorySettings, ["recordId"]);
15886
+ }
15887
+ return this.updateSettings(
15888
+ {
15889
+ target,
15890
+ stepParams: (0, import_service_utils.buildDefinedPayload)({
15891
+ ...cardSettings ? { cardSettings } : {},
15892
+ ...changes.resource ? {
15893
+ resourceSettings: {
15894
+ init: normalizedRecordHistoryResourceChange == null ? void 0 : normalizedRecordHistoryResourceChange.resourceInit
15895
+ }
15896
+ } : {},
15897
+ ...recordHistorySettings ? {
15898
+ recordHistorySettings
15899
+ } : {}
15900
+ })
15901
+ },
15902
+ {
15903
+ ...options,
15904
+ replaceRecordHistorySettings: !!resourceChange
15905
+ }
15906
+ );
15907
+ }
15145
15908
  async configureJSBlock(target, changes, options) {
15146
15909
  const allowedKeys = (0, import_configure_options.getConfigureOptionKeysForUse)("JSBlockModel");
15147
15910
  (0, import_service_utils.assertSupportedSimpleChanges)("jsBlock", changes, allowedKeys);
@@ -15720,57 +16483,921 @@ class FlowSurfacesService {
15720
16483
  });
15721
16484
  });
15722
16485
  }
15723
- async configureActionNode(target, use, changes, options) {
15724
- const currentNode = options.current || (target.uid ? await this.repository.findModelById(target.uid, {
15725
- transaction: options.transaction,
15726
- includeAsyncNode: true
15727
- }) : null);
15728
- changes = await this.normalizeActionPanelActionChanges(changes, options);
15729
- const allowedKeys = (0, import_configure_options.getConfigureOptionKeysForUse)(use);
15730
- (0, import_service_utils.assertSupportedSimpleChanges)("action", changes, allowedKeys);
15731
- const normalizedDefaultFilter = (0, import_service_utils.hasOwnDefined)(changes, "defaultFilter") ? this.normalizeFilterActionDefaultFilterValue(changes.defaultFilter) : void 0;
16486
+ isAIEmployeeActionUse(use) {
16487
+ return String(use || "").trim() === AI_EMPLOYEE_ACTION_USE;
16488
+ }
16489
+ hasAIEmployeePublicSettings(settings) {
16490
+ return import_lodash.default.isPlainObject(settings) && AI_EMPLOYEE_PUBLIC_SETTING_KEYS.some((key) => Object.prototype.hasOwnProperty.call(settings, key));
16491
+ }
16492
+ assertOnlyAIEmployeePublicSettings(actionName, settings) {
16493
+ const unsupportedKeys = Object.keys(settings || {}).filter((key) => !AI_EMPLOYEE_PUBLIC_SETTING_KEYS.includes(key));
16494
+ if (unsupportedKeys.length) {
16495
+ (0, import_errors.throwBadRequest)(
16496
+ `flowSurfaces ${actionName} AI employee settings do not support keys: ${unsupportedKeys.join(", ")}`
16497
+ );
16498
+ }
16499
+ }
16500
+ assertOnlyAIEmployeeNestedPublicSettings(actionName, path, value, allowedKeys) {
16501
+ const unsupportedKeys = Object.keys(value || {}).filter((key) => !allowedKeys.includes(key));
16502
+ if (!unsupportedKeys.length) {
16503
+ return;
16504
+ }
16505
+ (0, import_errors.throwBadRequest)(`flowSurfaces ${actionName} ${path} does not support key '${unsupportedKeys[0]}'`);
16506
+ }
16507
+ assertNoAIEmployeeInternalPropSettings(actionName, values) {
16508
+ const props = values == null ? void 0 : values.props;
16509
+ if (!import_lodash.default.isPlainObject(props)) {
16510
+ return;
16511
+ }
16512
+ const unsupportedKeys = AI_EMPLOYEE_INTERNAL_PROP_KEYS.filter(
16513
+ (key) => Object.prototype.hasOwnProperty.call(props, key)
16514
+ );
16515
+ if (!unsupportedKeys.length) {
16516
+ return;
16517
+ }
16518
+ (0, import_errors.throwBadRequest)(
16519
+ `flowSurfaces ${actionName} AI employee action does not accept raw props.${unsupportedKeys.join(
16520
+ ", props."
16521
+ )}; use top-level username, auto, workContext, tasks or style instead`
16522
+ );
16523
+ }
16524
+ readAIEmployeePersistedTasks(current) {
16525
+ var _a;
16526
+ const stepTasks = import_lodash.default.get(current, ["stepParams", ...AI_EMPLOYEE_TASK_STEP_PARAMS_PATH]);
16527
+ if (Array.isArray(stepTasks)) {
16528
+ return stepTasks;
16529
+ }
16530
+ const legacyPropsTasks = (_a = current == null ? void 0 : current.props) == null ? void 0 : _a.tasks;
16531
+ return Array.isArray(legacyPropsTasks) ? legacyPropsTasks : [];
16532
+ }
16533
+ buildAIEmployeeTaskStepParams(tasks) {
15732
16534
  const stepParams = {};
15733
- if ((0, import_service_utils.hasDefinedValue)(changes, ["title", "tooltip", "icon", "type", "danger", "color", "linkageRules"])) {
15734
- stepParams.buttonSettings = {
15735
- ...(0, import_service_utils.hasDefinedValue)(changes, ["title", "tooltip", "icon", "type", "danger", "color"]) ? {
15736
- general: (0, import_service_utils.buildDefinedPayload)({
15737
- title: changes.title,
15738
- tooltip: changes.tooltip,
15739
- icon: changes.icon,
15740
- type: changes.type,
15741
- danger: changes.danger,
15742
- color: changes.color
15743
- })
15744
- } : {},
15745
- ...(0, import_service_utils.hasOwnDefined)(changes, "linkageRules") ? { linkageRules: { value: changes.linkageRules } } : {}
15746
- };
16535
+ import_lodash.default.set(stepParams, AI_EMPLOYEE_TASK_STEP_PARAMS_PATH, import_lodash.default.cloneDeep(tasks));
16536
+ return stepParams;
16537
+ }
16538
+ mergeAIEmployeeActionSettingsPayload(current, values, payload) {
16539
+ if (Object.keys(payload.props).length) {
16540
+ values.props = import_lodash.default.merge({}, values.props || {}, payload.props);
15747
16541
  }
15748
- if ((0, import_service_utils.hasOwnDefined)(changes, "filterableFieldNames") || (0, import_service_utils.hasOwnDefined)(changes, "defaultFilter")) {
15749
- if (use !== "FilterActionModel") {
15750
- (0, import_errors.throwBadRequest)(`flowSurfaces configure action '${use}' does not support filterableFieldNames/defaultFilter`);
15751
- }
15752
- stepParams.filterSettings = (0, import_service_utils.buildDefinedPayload)({
15753
- ...(0, import_service_utils.hasOwnDefined)(changes, "filterableFieldNames") ? {
15754
- filterableFieldNames: {
15755
- filterableFieldNames: import_lodash.default.cloneDeep(changes.filterableFieldNames)
15756
- }
15757
- } : {},
15758
- ...(0, import_service_utils.hasOwnDefined)(changes, "defaultFilter") ? {
15759
- defaultFilter: {
15760
- defaultFilter: normalizedDefaultFilter
15761
- }
15762
- } : {}
16542
+ if (Object.keys(payload.stepParams).length) {
16543
+ values.stepParams = import_lodash.default.mergeWith({}, values.stepParams || {}, payload.stepParams, (_currentValue, nextValue) => {
16544
+ if (Array.isArray(nextValue)) {
16545
+ return import_lodash.default.cloneDeep(nextValue);
16546
+ }
16547
+ return void 0;
15763
16548
  });
15764
16549
  }
15765
- if ((0, import_service_utils.hasOwnDefined)(changes, "approvalReturn")) {
15766
- if (use !== "ProcessFormReturnModel") {
15767
- (0, import_errors.throwBadRequest)(`flowSurfaces configure action '${use}' does not support approvalReturn`);
16550
+ if (import_lodash.default.has(payload.stepParams, AI_EMPLOYEE_TASK_STEP_PARAMS_PATH) && this.isAIEmployeeActionUse(current == null ? void 0 : current.use)) {
16551
+ if (import_lodash.default.isPlainObject(values.props)) {
16552
+ delete values.props.tasks;
15768
16553
  }
15769
- import_lodash.default.set(
15770
- stepParams,
15771
- ["clickSettings", "saveResource", "approvalReturnNodeSettings"],
15772
- import_lodash.default.cloneDeep(changes.approvalReturn || {})
15773
- );
16554
+ }
16555
+ }
16556
+ syncAIEmployeeTaskStepParamsForUpdateSettings(current, nextPayload) {
16557
+ var _a;
16558
+ if (!this.isAIEmployeeActionUse(current == null ? void 0 : current.use)) {
16559
+ return;
16560
+ }
16561
+ const legacyPropsTasks = (_a = current == null ? void 0 : current.props) == null ? void 0 : _a.tasks;
16562
+ const hasLegacyPropsTasks = Array.isArray(legacyPropsTasks);
16563
+ const hasNextStepTasks = import_lodash.default.has(nextPayload, ["stepParams", ...AI_EMPLOYEE_TASK_STEP_PARAMS_PATH]);
16564
+ const currentStepTasks = import_lodash.default.get(current, ["stepParams", ...AI_EMPLOYEE_TASK_STEP_PARAMS_PATH]);
16565
+ if (!hasNextStepTasks && hasLegacyPropsTasks && !Array.isArray(currentStepTasks)) {
16566
+ nextPayload.stepParams = import_lodash.default.mergeWith(
16567
+ {},
16568
+ (current == null ? void 0 : current.stepParams) || {},
16569
+ this.buildAIEmployeeTaskStepParams(legacyPropsTasks),
16570
+ (_currentValue, nextValue) => {
16571
+ if (Array.isArray(nextValue)) {
16572
+ return import_lodash.default.cloneDeep(nextValue);
16573
+ }
16574
+ return void 0;
16575
+ }
16576
+ );
16577
+ }
16578
+ if (!hasLegacyPropsTasks && !import_lodash.default.has(nextPayload, ["props", "tasks"])) {
16579
+ return;
16580
+ }
16581
+ const nextProps = import_lodash.default.cloneDeep(nextPayload.props ?? (current == null ? void 0 : current.props) ?? {});
16582
+ delete nextProps.tasks;
16583
+ nextPayload.props = nextProps;
16584
+ }
16585
+ assertAIEmployeePluginEnabled(actionName, enabledPackages) {
16586
+ if (!enabledPackages.has(AI_EMPLOYEE_OWNER_PLUGIN)) {
16587
+ (0, import_errors.throwBadRequest)(
16588
+ `flowSurfaces ${actionName} action 'aiEmployee' is not available in the current app instance because plugin '${AI_EMPLOYEE_OWNER_PLUGIN}' is not enabled`
16589
+ );
16590
+ }
16591
+ }
16592
+ readRecordPlainObject(record) {
16593
+ if (!record) {
16594
+ return null;
16595
+ }
16596
+ if (typeof record.toJSON === "function") {
16597
+ return record.toJSON();
16598
+ }
16599
+ if (typeof record.get === "function") {
16600
+ try {
16601
+ return record.get({ plain: true });
16602
+ } catch (error) {
16603
+ return record.get();
16604
+ }
16605
+ }
16606
+ return record;
16607
+ }
16608
+ readRecordField(record, field) {
16609
+ var _a;
16610
+ return ((_a = record == null ? void 0 : record.get) == null ? void 0 : _a.call(record, field)) ?? (record == null ? void 0 : record[field]);
16611
+ }
16612
+ normalizeFlowSurfaceRequestRoles(currentRoles) {
16613
+ return import_lodash.default.castArray(currentRoles || []).map((role) => String(role || "").trim()).filter(Boolean);
16614
+ }
16615
+ async assertRequestRolesCanUseAIEmployeeUsername(actionName, username, options) {
16616
+ const currentRoles = this.normalizeFlowSurfaceRequestRoles(options.currentRoles);
16617
+ if (!currentRoles.length || currentRoles.includes("root")) {
16618
+ return;
16619
+ }
16620
+ if (!this.db.getCollection("rolesAiEmployees")) {
16621
+ (0, import_errors.throwBadRequest)(
16622
+ `flowSurfaces ${actionName} action 'aiEmployee' cannot validate role visibility because collection 'rolesAiEmployees' is unavailable; enable plugin '${AI_EMPLOYEE_OWNER_PLUGIN}' first`
16623
+ );
16624
+ }
16625
+ const grants = await this.db.getRepository("rolesAiEmployees").find({
16626
+ filter: {
16627
+ roleName: currentRoles,
16628
+ aiEmployee: username
16629
+ },
16630
+ transaction: options.transaction
16631
+ });
16632
+ if (!import_lodash.default.castArray(grants).length) {
16633
+ (0, import_errors.throwBadRequest)(`flowSurfaces ${actionName} AI employee username '${username}' is not visible to current roles`);
16634
+ }
16635
+ }
16636
+ async assertVisibleAIEmployeeUsername(actionName, username, options = {}) {
16637
+ if (!this.db.getCollection("aiEmployees")) {
16638
+ (0, import_errors.throwBadRequest)(
16639
+ `flowSurfaces ${actionName} action 'aiEmployee' cannot validate username because collection 'aiEmployees' is unavailable; enable plugin '${AI_EMPLOYEE_OWNER_PLUGIN}' first`
16640
+ );
16641
+ }
16642
+ const record = await this.db.getRepository("aiEmployees").findOne({
16643
+ filter: {
16644
+ username
16645
+ },
16646
+ transaction: options.transaction
16647
+ });
16648
+ if (!record) {
16649
+ (0, import_errors.throwBadRequest)(`flowSurfaces ${actionName} AI employee username '${username}' does not exist`);
16650
+ }
16651
+ const plain = this.readRecordPlainObject(record) || {};
16652
+ const enabled = this.readRecordField(record, "enabled") ?? plain.enabled;
16653
+ const deprecated = this.readRecordField(record, "deprecated") ?? plain.deprecated;
16654
+ const category = this.readRecordField(record, "category") ?? plain.category;
16655
+ if (enabled === false || deprecated === true || category === "developer") {
16656
+ (0, import_errors.throwBadRequest)(`flowSurfaces ${actionName} AI employee username '${username}' is not visible`);
16657
+ }
16658
+ await this.assertRequestRolesCanUseAIEmployeeUsername(actionName, username, options);
16659
+ }
16660
+ normalizeAIEmployeeUsername(actionName, value) {
16661
+ const username = typeof value === "string" ? value.trim() : "";
16662
+ if (!username) {
16663
+ (0, import_errors.throwBadRequest)(`flowSurfaces ${actionName} AI employee settings.username must be a non-empty string`);
16664
+ }
16665
+ return username;
16666
+ }
16667
+ assertAIEmployeeWorkContextType(actionName, itemPath, item) {
16668
+ if (String(item.type || "").trim() !== "flow-model") {
16669
+ (0, import_errors.throwBadRequest)(`flowSurfaces ${actionName} ${itemPath}.type must be 'flow-model'`);
16670
+ }
16671
+ }
16672
+ normalizeAIEmployeeWorkContext(actionName, value, options) {
16673
+ if (import_lodash.default.isUndefined(value) || value === null) {
16674
+ return [];
16675
+ }
16676
+ if (!Array.isArray(value)) {
16677
+ (0, import_errors.throwBadRequest)(`flowSurfaces ${actionName} ${options.path} must be an array`);
16678
+ }
16679
+ return value.map((item, index) => {
16680
+ const itemPath = `${options.path}[${index}]`;
16681
+ if (!import_lodash.default.isPlainObject(item)) {
16682
+ (0, import_errors.throwBadRequest)(`flowSurfaces ${actionName} ${itemPath} must be an object`);
16683
+ }
16684
+ this.assertOnlyAIEmployeeNestedPublicSettings(
16685
+ actionName,
16686
+ itemPath,
16687
+ item,
16688
+ AI_EMPLOYEE_WORK_CONTEXT_PUBLIC_KEYS
16689
+ );
16690
+ this.assertAIEmployeeWorkContextType(actionName, itemPath, item);
16691
+ if (Object.prototype.hasOwnProperty.call(item, "target") && typeof item.target !== "string") {
16692
+ (0, import_errors.throwBadRequest)(`flowSurfaces ${actionName} ${itemPath}.target must be 'self' or a string block key`);
16693
+ }
16694
+ const hasTarget = Object.prototype.hasOwnProperty.call(item, "target");
16695
+ const target = hasTarget ? item.target.trim() : "";
16696
+ if (hasTarget && !target) {
16697
+ (0, import_errors.throwBadRequest)(`flowSurfaces ${actionName} ${itemPath}.target must be 'self' or a string block key`);
16698
+ }
16699
+ const uidValue = typeof item.uid === "string" ? item.uid.trim() : "";
16700
+ if (!target) {
16701
+ if (!uidValue) {
16702
+ (0, import_errors.throwBadRequest)(`flowSurfaces ${actionName} ${itemPath} requires uid or target`);
16703
+ }
16704
+ return {
16705
+ type: "flow-model",
16706
+ uid: uidValue
16707
+ };
16708
+ }
16709
+ let uidValueFromTarget;
16710
+ if (target === "self") {
16711
+ uidValueFromTarget = options.selfUid;
16712
+ } else if (options.keyMap) {
16713
+ uidValueFromTarget = (0, import_compose_compiler.resolveComposeTargetKey)(target, options.keyMap, "AI employee workContext");
16714
+ } else {
16715
+ (0, import_errors.throwBadRequest)(
16716
+ `flowSurfaces ${actionName} ${itemPath}.target only supports 'self' in localized writes; pass uid for existing Flow Model context`
16717
+ );
16718
+ }
16719
+ if (!uidValueFromTarget) {
16720
+ (0, import_errors.throwBadRequest)(`flowSurfaces ${actionName} ${itemPath}.target could not resolve a Flow Model uid`);
16721
+ }
16722
+ return {
16723
+ type: "flow-model",
16724
+ uid: uidValueFromTarget
16725
+ };
16726
+ });
16727
+ }
16728
+ normalizeAIEmployeeTaskModel(actionName, path, value) {
16729
+ if (import_lodash.default.isUndefined(value) || value === null) {
16730
+ return value;
16731
+ }
16732
+ if (!import_lodash.default.isPlainObject(value)) {
16733
+ (0, import_errors.throwBadRequest)(`flowSurfaces ${actionName} ${path} must be an object or null`);
16734
+ }
16735
+ this.assertOnlyAIEmployeeNestedPublicSettings(
16736
+ actionName,
16737
+ path,
16738
+ value,
16739
+ AI_EMPLOYEE_TASK_MODEL_PUBLIC_KEYS
16740
+ );
16741
+ const llmService = typeof value.llmService === "string" ? value.llmService.trim() : "";
16742
+ const model = typeof value.model === "string" ? value.model.trim() : "";
16743
+ if (!llmService || !model) {
16744
+ (0, import_errors.throwBadRequest)(`flowSurfaces ${actionName} ${path} requires non-empty llmService and model`);
16745
+ }
16746
+ return {
16747
+ ...import_lodash.default.cloneDeep(value),
16748
+ llmService,
16749
+ model
16750
+ };
16751
+ }
16752
+ normalizeAIEmployeeSkillSettings(actionName, path, value) {
16753
+ if (import_lodash.default.isUndefined(value) || value === null) {
16754
+ return value;
16755
+ }
16756
+ if (!import_lodash.default.isPlainObject(value)) {
16757
+ (0, import_errors.throwBadRequest)(`flowSurfaces ${actionName} ${path} must be an object or null`);
16758
+ }
16759
+ this.assertOnlyAIEmployeeNestedPublicSettings(
16760
+ actionName,
16761
+ path,
16762
+ value,
16763
+ AI_EMPLOYEE_SKILL_SETTINGS_PUBLIC_KEYS
16764
+ );
16765
+ const next = import_lodash.default.cloneDeep(value);
16766
+ if (Object.prototype.hasOwnProperty.call(next, "skills") && !Array.isArray(next.skills)) {
16767
+ (0, import_errors.throwBadRequest)(`flowSurfaces ${actionName} ${path}.skills must be an array`);
16768
+ }
16769
+ if (Object.prototype.hasOwnProperty.call(next, "tools") && !Array.isArray(next.tools)) {
16770
+ (0, import_errors.throwBadRequest)(`flowSurfaces ${actionName} ${path}.tools must be an array`);
16771
+ }
16772
+ if (Object.prototype.hasOwnProperty.call(next, "skillsVersion") && typeof next.skillsVersion !== "number") {
16773
+ (0, import_errors.throwBadRequest)(`flowSurfaces ${actionName} ${path}.skillsVersion must be a number`);
16774
+ }
16775
+ if (Object.prototype.hasOwnProperty.call(next, "toolsVersion") && typeof next.toolsVersion !== "number") {
16776
+ (0, import_errors.throwBadRequest)(`flowSurfaces ${actionName} ${path}.toolsVersion must be a number`);
16777
+ }
16778
+ const hasSkills = Object.prototype.hasOwnProperty.call(next, "skills");
16779
+ const hasTools = Object.prototype.hasOwnProperty.call(next, "tools");
16780
+ const hasSkillsVersion = Object.prototype.hasOwnProperty.call(next, "skillsVersion");
16781
+ const hasToolsVersion = Object.prototype.hasOwnProperty.call(next, "toolsVersion");
16782
+ if (hasSkills && hasTools && !hasSkillsVersion && !hasToolsVersion && Array.isArray(next.skills) && Array.isArray(next.tools) && next.skills.length === 0 && next.tools.length === 0) {
16783
+ return null;
16784
+ }
16785
+ if (hasSkills && !hasSkillsVersion) {
16786
+ next.skillsVersion = 2;
16787
+ }
16788
+ if (hasTools && !hasToolsVersion) {
16789
+ next.toolsVersion = 2;
16790
+ }
16791
+ return next;
16792
+ }
16793
+ collectAIEmployeePromptVariables(value) {
16794
+ if (!value.includes("{{")) {
16795
+ return [];
16796
+ }
16797
+ return [...value.matchAll(/\{\{\s*([\s\S]+?)\s*\}\}/g)].map(([raw, inner]) => ({
16798
+ raw,
16799
+ inner: String(inner || "").trim()
16800
+ }));
16801
+ }
16802
+ hasAIEmployeePromptVariables(tasks) {
16803
+ return import_lodash.default.castArray(tasks || []).some((task) => {
16804
+ const message = task == null ? void 0 : task.message;
16805
+ return typeof (message == null ? void 0 : message.system) === "string" && this.collectAIEmployeePromptVariables(message.system).length > 0 || typeof (message == null ? void 0 : message.user) === "string" && this.collectAIEmployeePromptVariables(message.user).length > 0;
16806
+ });
16807
+ }
16808
+ collectAIEmployeeContextPathEntries(context) {
16809
+ const result = /* @__PURE__ */ new Map();
16810
+ const visit = (prefix, info) => {
16811
+ if (!prefix || !info) {
16812
+ return;
16813
+ }
16814
+ result.set(prefix, info);
16815
+ if (info.dynamicProperties) {
16816
+ result.set(`${prefix}.*`, info.dynamicProperties);
16817
+ }
16818
+ for (const [childKey, childInfo] of Object.entries(info.properties || {})) {
16819
+ visit(`${prefix}.${childKey}`, childInfo);
16820
+ }
16821
+ };
16822
+ for (const [key, info] of Object.entries((context == null ? void 0 : context.vars) || {})) {
16823
+ visit(key, info);
16824
+ }
16825
+ return result;
16826
+ }
16827
+ isAIEmployeeContextInfoPathAllowed(info, segments) {
16828
+ var _a;
16829
+ if (!info) {
16830
+ return false;
16831
+ }
16832
+ if (!segments.length) {
16833
+ return true;
16834
+ }
16835
+ const [segment, ...rest] = segments;
16836
+ const staticChild = (_a = info.properties) == null ? void 0 : _a[segment];
16837
+ if (staticChild) {
16838
+ return this.isAIEmployeeContextInfoPathAllowed(staticChild, rest);
16839
+ }
16840
+ if (info.dynamicProperties) {
16841
+ return this.isAIEmployeeContextInfoPathAllowed(info.dynamicProperties, rest);
16842
+ }
16843
+ return false;
16844
+ }
16845
+ canResolveAIEmployeeContextPath(path, semantic) {
16846
+ var _a;
16847
+ return !!((_a = (0, import_context.buildFlowSurfaceContextResponse)({
16848
+ semantic,
16849
+ path,
16850
+ maxDepth: 1
16851
+ }).vars) == null ? void 0 : _a[path]);
16852
+ }
16853
+ isAIEmployeeContextPathAllowed(path, validation) {
16854
+ if (validation.contextPaths.has(path)) {
16855
+ return true;
16856
+ }
16857
+ for (const [allowedPath, info] of validation.contextPaths) {
16858
+ if (!allowedPath.endsWith(".*")) {
16859
+ continue;
16860
+ }
16861
+ const prefix = allowedPath.slice(0, -2);
16862
+ if (!path.startsWith(`${prefix}.`)) {
16863
+ continue;
16864
+ }
16865
+ const dynamicSegments = path.slice(prefix.length + 1).split(".").filter(Boolean);
16866
+ if (dynamicSegments.length && this.isAIEmployeeContextInfoPathAllowed(info, dynamicSegments.slice(1))) {
16867
+ return true;
16868
+ }
16869
+ }
16870
+ return this.canResolveAIEmployeeContextPath(path, validation.semantic);
16871
+ }
16872
+ extractAIEmployeePromptContextPath(expression) {
16873
+ const normalized = String(expression || "").trim();
16874
+ if (normalized === "ctx") {
16875
+ return "";
16876
+ }
16877
+ if (!normalized.startsWith("ctx.")) {
16878
+ return null;
16879
+ }
16880
+ const path = normalized.slice(4).trim();
16881
+ return (0, import_context.isBareFlowContextPath)(path) ? path : null;
16882
+ }
16883
+ buildAIEmployeePromptVariableHint(targetUid) {
16884
+ return `Call flowSurfaces:context${targetUid ? ` with target.uid "${targetUid}"` : ""} to inspect available ctx paths before writing prompt variables.`;
16885
+ }
16886
+ throwAIEmployeePromptVariableInvalid(input) {
16887
+ (0, import_errors.throwBadRequest)(
16888
+ `flowSurfaces ${input.actionName} ${input.fieldPath} variable "${input.variable}" is not allowed: ${input.reason}. Use a concrete ctx path such as "{{ ctx.record.id }}" only when that path is available. ${this.buildAIEmployeePromptVariableHint(
16889
+ input.targetUid
16890
+ )}`,
16891
+ AI_EMPLOYEE_PROMPT_VARIABLE_INVALID,
16892
+ {
16893
+ path: input.fieldPath,
16894
+ details: (0, import_service_utils.buildDefinedPayload)({
16895
+ variable: input.variable,
16896
+ contextPath: input.path,
16897
+ targetUid: input.targetUid
16898
+ })
16899
+ }
16900
+ );
16901
+ }
16902
+ assertAIEmployeePromptVariablesAllowed(actionName, fieldPath, value, validation) {
16903
+ for (const variable of this.collectAIEmployeePromptVariables(value)) {
16904
+ const path = this.extractAIEmployeePromptContextPath(variable.inner);
16905
+ if (path === "") {
16906
+ this.throwAIEmployeePromptVariableInvalid({
16907
+ actionName,
16908
+ fieldPath,
16909
+ variable: variable.raw,
16910
+ targetUid: validation.targetUid,
16911
+ reason: "the whole ctx object is not a valid prompt variable; use a concrete ctx path"
16912
+ });
16913
+ }
16914
+ if (!path) {
16915
+ this.throwAIEmployeePromptVariableInvalid({
16916
+ actionName,
16917
+ fieldPath,
16918
+ variable: variable.raw,
16919
+ targetUid: validation.targetUid,
16920
+ reason: 'only simple ctx dot paths like "{{ ctx.record.id }}" are supported'
16921
+ });
16922
+ }
16923
+ if (!this.isAIEmployeeContextPathAllowed(path, validation)) {
16924
+ this.throwAIEmployeePromptVariableInvalid({
16925
+ actionName,
16926
+ fieldPath,
16927
+ variable: variable.raw,
16928
+ targetUid: validation.targetUid,
16929
+ path,
16930
+ reason: `path "${path}" is not available in the current Flow Surface context`
16931
+ });
16932
+ }
16933
+ }
16934
+ }
16935
+ assertAIEmployeeTaskPromptVariablesAllowed(actionName, tasks, validation, path = "settings.tasks") {
16936
+ if (!validation) {
16937
+ return;
16938
+ }
16939
+ tasks.forEach((task, index) => {
16940
+ const message = task == null ? void 0 : task.message;
16941
+ if (typeof (message == null ? void 0 : message.system) === "string") {
16942
+ this.assertAIEmployeePromptVariablesAllowed(
16943
+ actionName,
16944
+ `${path}[${index}].message.system`,
16945
+ message.system,
16946
+ validation
16947
+ );
16948
+ }
16949
+ if (typeof (message == null ? void 0 : message.user) === "string") {
16950
+ this.assertAIEmployeePromptVariablesAllowed(
16951
+ actionName,
16952
+ `${path}[${index}].message.user`,
16953
+ message.user,
16954
+ validation
16955
+ );
16956
+ }
16957
+ });
16958
+ }
16959
+ appendAIEmployeeCurrentRecordPromptVariable(value) {
16960
+ if (AI_EMPLOYEE_CURRENT_RECORD_PROMPT_VARIABLE_RE.test(value)) {
16961
+ return value;
16962
+ }
16963
+ return value ? `${value}
16964
+ ${AI_EMPLOYEE_CURRENT_RECORD_PROMPT_VARIABLE}` : AI_EMPLOYEE_CURRENT_RECORD_PROMPT_VARIABLE;
16965
+ }
16966
+ async resolveAIEmployeePromptActionTargetUid(context, transaction) {
16967
+ if (!context) {
16968
+ return void 0;
16969
+ }
16970
+ if (context.kind === "target") {
16971
+ return String(context.targetUid || "").trim() || void 0;
16972
+ }
16973
+ return String(context.ownerUid || "").trim() || void 0;
16974
+ }
16975
+ async buildAIEmployeePromptValidationContext(actionName, tasks, options) {
16976
+ var _a, _b;
16977
+ if (!this.hasAIEmployeePromptVariables(tasks)) {
16978
+ return void 0;
16979
+ }
16980
+ const targetUid = await this.resolveAIEmployeePromptActionTargetUid(options.promptContext, options.transaction);
16981
+ if (!targetUid) {
16982
+ (0, import_errors.throwBadRequest)(
16983
+ `flowSurfaces ${actionName} AI employee prompt variables require a resolvable Flow Surface context. ${this.buildAIEmployeePromptVariableHint()}`,
16984
+ AI_EMPLOYEE_PROMPT_VARIABLE_INVALID
16985
+ );
16986
+ }
16987
+ const target = { uid: targetUid };
16988
+ const resolved = await this.locator.resolve(target, { transaction: options.transaction });
16989
+ let semantic = await this.resolveContextSemantic(((_a = resolved == null ? void 0 : resolved.node) == null ? void 0 : _a.uid) || target.uid, resolved, options.transaction);
16990
+ if (((_b = options.promptContext) == null ? void 0 : _b.kind) === "container" && options.promptContext.scope === "record") {
16991
+ semantic = {
16992
+ ...semantic,
16993
+ recordCollection: semantic.recordCollection || semantic.collection || await this.resolveContextOwnerCollection(targetUid, options.transaction).catch(() => null)
16994
+ };
16995
+ }
16996
+ const context = (0, import_context.buildFlowSurfaceContextResponse)({
16997
+ semantic,
16998
+ maxDepth: AI_EMPLOYEE_PROMPT_CONTEXT_MAX_DEPTH
16999
+ });
17000
+ return {
17001
+ targetUid,
17002
+ semantic,
17003
+ contextPaths: this.collectAIEmployeeContextPathEntries(context)
17004
+ };
17005
+ }
17006
+ appendAIEmployeeCurrentRecordPromptVariableToTasks(tasks, validation) {
17007
+ if (!tasks.length || !validation || !this.isAIEmployeeContextPathAllowed("record", validation)) {
17008
+ return tasks;
17009
+ }
17010
+ return tasks.map((task) => {
17011
+ var _a;
17012
+ if (typeof ((_a = task == null ? void 0 : task.message) == null ? void 0 : _a.user) !== "string") {
17013
+ return task;
17014
+ }
17015
+ const next = import_lodash.default.cloneDeep(task);
17016
+ next.message.user = this.appendAIEmployeeCurrentRecordPromptVariable(next.message.user);
17017
+ return next;
17018
+ });
17019
+ }
17020
+ async assertAIEmployeeStepParamTaskPromptVariablesAllowedForUpdateSettings(current, nextPayload, writeTarget, options) {
17021
+ if (!this.isAIEmployeeActionUse(current == null ? void 0 : current.use) || !import_lodash.default.has(nextPayload, ["stepParams", ...AI_EMPLOYEE_TASK_STEP_PARAMS_PATH])) {
17022
+ return;
17023
+ }
17024
+ const tasks = import_lodash.default.get(nextPayload, ["stepParams", ...AI_EMPLOYEE_TASK_STEP_PARAMS_PATH]);
17025
+ if (!Array.isArray(tasks)) {
17026
+ return;
17027
+ }
17028
+ const actionName = options.openViewActionName || "updateSettings";
17029
+ this.assertAIEmployeeTaskPromptVariablesAllowed(
17030
+ actionName,
17031
+ tasks,
17032
+ await this.buildAIEmployeePromptValidationContext(actionName, tasks, {
17033
+ transaction: options.transaction,
17034
+ promptContext: {
17035
+ kind: "target",
17036
+ targetUid: (current == null ? void 0 : current.uid) || writeTarget.uid
17037
+ }
17038
+ }),
17039
+ "stepParams.shortcutSettings.editTasks.tasks"
17040
+ );
17041
+ }
17042
+ async normalizeAIEmployeeStepParamTasksForUpdateSettings(current, nextPayload, writeTarget, options) {
17043
+ if (!this.isAIEmployeeActionUse(current == null ? void 0 : current.use) || !import_lodash.default.has(nextPayload, ["stepParams", ...AI_EMPLOYEE_TASK_STEP_PARAMS_PATH])) {
17044
+ return;
17045
+ }
17046
+ const tasks = import_lodash.default.get(nextPayload, ["stepParams", ...AI_EMPLOYEE_TASK_STEP_PARAMS_PATH]);
17047
+ if (!Array.isArray(tasks)) {
17048
+ return;
17049
+ }
17050
+ const actionName = options.openViewActionName || "updateSettings";
17051
+ const normalizedTasks = this.normalizeAIEmployeeTasks(
17052
+ actionName,
17053
+ tasks,
17054
+ this.readAIEmployeePersistedTasks(current),
17055
+ {
17056
+ selfUid: await this.resolveAIEmployeeActionSelfUid(current || { uid: writeTarget.uid }, options.transaction),
17057
+ path: "stepParams.shortcutSettings.editTasks.tasks"
17058
+ }
17059
+ );
17060
+ import_lodash.default.set(nextPayload, ["stepParams", ...AI_EMPLOYEE_TASK_STEP_PARAMS_PATH], normalizedTasks);
17061
+ }
17062
+ normalizeAIEmployeeTaskMessage(actionName, path, value, existing, options) {
17063
+ if (!import_lodash.default.isPlainObject(value)) {
17064
+ (0, import_errors.throwBadRequest)(`flowSurfaces ${actionName} ${path} must be an object`);
17065
+ }
17066
+ this.assertOnlyAIEmployeeNestedPublicSettings(
17067
+ actionName,
17068
+ path,
17069
+ value,
17070
+ AI_EMPLOYEE_TASK_MESSAGE_PUBLIC_KEYS
17071
+ );
17072
+ const nextMessage = import_lodash.default.pick(
17073
+ import_lodash.default.isPlainObject(existing) ? import_lodash.default.cloneDeep(existing) : {},
17074
+ AI_EMPLOYEE_TASK_MESSAGE_PUBLIC_KEYS
17075
+ );
17076
+ if (Object.prototype.hasOwnProperty.call(value, "system")) {
17077
+ nextMessage.system = value.system;
17078
+ }
17079
+ if (Object.prototype.hasOwnProperty.call(value, "user")) {
17080
+ nextMessage.user = value.user;
17081
+ }
17082
+ if (Object.prototype.hasOwnProperty.call(nextMessage, "system") && typeof nextMessage.system !== "string") {
17083
+ (0, import_errors.throwBadRequest)(`flowSurfaces ${actionName} ${path}.system must be a string`);
17084
+ }
17085
+ if (Object.prototype.hasOwnProperty.call(nextMessage, "user") && typeof nextMessage.user !== "string") {
17086
+ (0, import_errors.throwBadRequest)(`flowSurfaces ${actionName} ${path}.user must be a string`);
17087
+ }
17088
+ if (Object.prototype.hasOwnProperty.call(value, "workContext")) {
17089
+ nextMessage.workContext = this.normalizeAIEmployeeWorkContext(actionName, value.workContext, {
17090
+ selfUid: options.selfUid,
17091
+ keyMap: options.keyMap,
17092
+ path: `${path}.workContext`
17093
+ });
17094
+ }
17095
+ return nextMessage;
17096
+ }
17097
+ normalizeAIEmployeeTaskPatch(actionName, patch, existing, options) {
17098
+ if (!import_lodash.default.isPlainObject(patch)) {
17099
+ (0, import_errors.throwBadRequest)(`flowSurfaces ${actionName} ${options.path} must be an object`);
17100
+ }
17101
+ const next = import_lodash.default.pick(import_lodash.default.isPlainObject(existing) ? import_lodash.default.cloneDeep(existing) : {}, AI_EMPLOYEE_TASK_PUBLIC_SETTING_KEYS);
17102
+ Object.entries(patch).forEach(([key, value]) => {
17103
+ if (!AI_EMPLOYEE_TASK_PUBLIC_SETTING_KEYS.includes(key)) {
17104
+ (0, import_errors.throwBadRequest)(`flowSurfaces ${actionName} ${options.path} does not support key '${key}'`);
17105
+ }
17106
+ if (key === "message") {
17107
+ next.message = this.normalizeAIEmployeeTaskMessage(actionName, `${options.path}.message`, value, next.message, {
17108
+ selfUid: options.selfUid,
17109
+ keyMap: options.keyMap
17110
+ });
17111
+ return;
17112
+ }
17113
+ if (key === "title") {
17114
+ if (typeof value !== "string") {
17115
+ (0, import_errors.throwBadRequest)(`flowSurfaces ${actionName} ${options.path}.title must be a string`);
17116
+ }
17117
+ next.title = value;
17118
+ return;
17119
+ }
17120
+ if (key === "autoSend" || key === "webSearch") {
17121
+ if (typeof value !== "boolean") {
17122
+ (0, import_errors.throwBadRequest)(`flowSurfaces ${actionName} ${options.path}.${key} must be a boolean`);
17123
+ }
17124
+ next[key] = value;
17125
+ return;
17126
+ }
17127
+ if (key === "model") {
17128
+ next.model = this.normalizeAIEmployeeTaskModel(actionName, `${options.path}.model`, value);
17129
+ return;
17130
+ }
17131
+ if (key === "skillSettings") {
17132
+ const normalizedSkillSettings = this.normalizeAIEmployeeSkillSettings(
17133
+ actionName,
17134
+ `${options.path}.skillSettings`,
17135
+ value
17136
+ );
17137
+ next.skillSettings = normalizedSkillSettings && import_lodash.default.isPlainObject(normalizedSkillSettings) ? {
17138
+ ...import_lodash.default.isPlainObject(next.skillSettings) ? import_lodash.default.cloneDeep(next.skillSettings) : {},
17139
+ ...normalizedSkillSettings
17140
+ } : normalizedSkillSettings;
17141
+ return;
17142
+ }
17143
+ });
17144
+ if (!import_lodash.default.isPlainObject(next.message)) {
17145
+ next.message = {};
17146
+ }
17147
+ if (import_lodash.default.isPlainObject(next.skillSettings)) {
17148
+ if (Array.isArray(next.skillSettings.skills) && !Object.prototype.hasOwnProperty.call(next.skillSettings, "skillsVersion")) {
17149
+ next.skillSettings.skillsVersion = 2;
17150
+ }
17151
+ if (Array.isArray(next.skillSettings.tools) && !Object.prototype.hasOwnProperty.call(next.skillSettings, "toolsVersion")) {
17152
+ next.skillSettings.toolsVersion = 2;
17153
+ }
17154
+ }
17155
+ return next;
17156
+ }
17157
+ normalizeAIEmployeeTasks(actionName, value, currentTasks, options) {
17158
+ if (import_lodash.default.isUndefined(value) || value === null) {
17159
+ return [];
17160
+ }
17161
+ if (!Array.isArray(value)) {
17162
+ (0, import_errors.throwBadRequest)(`flowSurfaces ${actionName} ${options.path} must be an array`);
17163
+ }
17164
+ if (!value.length) {
17165
+ return [];
17166
+ }
17167
+ const existingTasks = Array.isArray(currentTasks) ? import_lodash.default.cloneDeep(currentTasks) : [];
17168
+ const nextTasks = [...existingTasks];
17169
+ value.forEach((task, index) => {
17170
+ nextTasks[index] = this.normalizeAIEmployeeTaskPatch(actionName, task, existingTasks[index], {
17171
+ selfUid: options.selfUid,
17172
+ keyMap: options.keyMap,
17173
+ path: `${options.path}[${index}]`
17174
+ });
17175
+ });
17176
+ return nextTasks;
17177
+ }
17178
+ normalizeAIEmployeeActionSettingsReferences(actionName, settings, options) {
17179
+ if (!this.hasAIEmployeePublicSettings(settings)) {
17180
+ return settings;
17181
+ }
17182
+ const nextSettings = import_lodash.default.cloneDeep(settings || {});
17183
+ if (Object.prototype.hasOwnProperty.call(nextSettings, "workContext")) {
17184
+ nextSettings.workContext = this.normalizeAIEmployeeWorkContext(actionName, nextSettings.workContext, {
17185
+ ...options,
17186
+ path: "settings.workContext"
17187
+ });
17188
+ }
17189
+ if (Object.prototype.hasOwnProperty.call(nextSettings, "tasks")) {
17190
+ nextSettings.tasks = this.normalizeAIEmployeeTasks(actionName, nextSettings.tasks, [], {
17191
+ ...options,
17192
+ path: "settings.tasks"
17193
+ });
17194
+ }
17195
+ return nextSettings;
17196
+ }
17197
+ async normalizeAIEmployeeActionPublicSettings(actionName, settings, options) {
17198
+ var _a, _b;
17199
+ this.assertAIEmployeePluginEnabled(actionName, options.enabledPackages);
17200
+ if (!import_lodash.default.isPlainObject(settings)) {
17201
+ (0, import_errors.throwBadRequest)(`flowSurfaces ${actionName} AI employee settings must be an object`);
17202
+ }
17203
+ this.assertOnlyAIEmployeePublicSettings(actionName, settings);
17204
+ const currentProps = import_lodash.default.isPlainObject((_a = options.current) == null ? void 0 : _a.props) ? options.current.props : {};
17205
+ const hasUsername = Object.prototype.hasOwnProperty.call(settings, "username");
17206
+ const effectiveUsername = hasUsername ? this.normalizeAIEmployeeUsername(actionName, settings.username) : String(((_b = currentProps == null ? void 0 : currentProps.aiEmployee) == null ? void 0 : _b.username) || "").trim();
17207
+ if (!effectiveUsername && (options.requireUsername || this.hasAIEmployeePublicSettings(settings))) {
17208
+ (0, import_errors.throwBadRequest)(`flowSurfaces ${actionName} AI employee settings.username is required`);
17209
+ }
17210
+ if (effectiveUsername) {
17211
+ await this.assertVisibleAIEmployeeUsername(actionName, effectiveUsername, {
17212
+ currentRoles: options.currentRoles,
17213
+ transaction: options.transaction
17214
+ });
17215
+ }
17216
+ const props = {};
17217
+ const stepParams = {};
17218
+ if (effectiveUsername && (hasUsername || options.requireUsername)) {
17219
+ props.aiEmployee = {
17220
+ ...import_lodash.default.isPlainObject(currentProps.aiEmployee) ? import_lodash.default.cloneDeep(currentProps.aiEmployee) : {},
17221
+ username: effectiveUsername
17222
+ };
17223
+ }
17224
+ if (Object.prototype.hasOwnProperty.call(settings, "auto") || options.requireUsername) {
17225
+ const auto = Object.prototype.hasOwnProperty.call(settings, "auto") ? settings.auto : typeof currentProps.auto === "boolean" ? currentProps.auto : false;
17226
+ if (typeof auto !== "boolean") {
17227
+ (0, import_errors.throwBadRequest)(`flowSurfaces ${actionName} AI employee settings.auto must be a boolean`);
17228
+ }
17229
+ props.auto = auto;
17230
+ }
17231
+ if (Object.prototype.hasOwnProperty.call(settings, "workContext") || options.requireUsername) {
17232
+ const rawWorkContext = Object.prototype.hasOwnProperty.call(settings, "workContext") ? settings.workContext : [{ type: "flow-model", target: "self" }];
17233
+ props.context = {
17234
+ ...import_lodash.default.isPlainObject(currentProps.context) ? import_lodash.default.cloneDeep(currentProps.context) : {},
17235
+ workContext: this.normalizeAIEmployeeWorkContext(actionName, rawWorkContext, {
17236
+ selfUid: options.selfUid,
17237
+ keyMap: options.keyMap,
17238
+ path: "settings.workContext"
17239
+ })
17240
+ };
17241
+ }
17242
+ if (Object.prototype.hasOwnProperty.call(settings, "tasks")) {
17243
+ const normalizedTasks = this.normalizeAIEmployeeTasks(
17244
+ actionName,
17245
+ settings.tasks,
17246
+ this.readAIEmployeePersistedTasks(options.current),
17247
+ {
17248
+ selfUid: options.selfUid,
17249
+ keyMap: options.keyMap,
17250
+ path: "settings.tasks"
17251
+ }
17252
+ );
17253
+ const validation = options.promptContext && normalizedTasks.length ? await this.buildAIEmployeePromptValidationContext(
17254
+ actionName,
17255
+ [
17256
+ {
17257
+ message: {
17258
+ user: AI_EMPLOYEE_CURRENT_RECORD_PROMPT_VARIABLE
17259
+ }
17260
+ }
17261
+ ],
17262
+ {
17263
+ transaction: options.transaction,
17264
+ promptContext: options.promptContext
17265
+ }
17266
+ ) : await this.buildAIEmployeePromptValidationContext(actionName, normalizedTasks, {
17267
+ transaction: options.transaction,
17268
+ promptContext: options.promptContext
17269
+ });
17270
+ const tasks = this.appendAIEmployeeCurrentRecordPromptVariableToTasks(normalizedTasks, validation);
17271
+ this.assertAIEmployeeTaskPromptVariablesAllowed(actionName, tasks, validation);
17272
+ import_lodash.default.merge(stepParams, this.buildAIEmployeeTaskStepParams(tasks));
17273
+ }
17274
+ if (Object.prototype.hasOwnProperty.call(settings, "style") || options.requireUsername) {
17275
+ const style = Object.prototype.hasOwnProperty.call(settings, "style") ? settings.style : {};
17276
+ if (!import_lodash.default.isUndefined(style) && style !== null && !import_lodash.default.isPlainObject(style)) {
17277
+ (0, import_errors.throwBadRequest)(`flowSurfaces ${actionName} AI employee settings.style must be an object`);
17278
+ }
17279
+ if (import_lodash.default.isPlainObject(style)) {
17280
+ this.assertOnlyAIEmployeeNestedPublicSettings(
17281
+ actionName,
17282
+ "settings.style",
17283
+ style,
17284
+ AI_EMPLOYEE_STYLE_PUBLIC_KEYS
17285
+ );
17286
+ if (Object.prototype.hasOwnProperty.call(style, "size") && typeof style.size !== "number") {
17287
+ (0, import_errors.throwBadRequest)(`flowSurfaces ${actionName} AI employee settings.style.size must be a number`);
17288
+ }
17289
+ if (Object.prototype.hasOwnProperty.call(style, "mask") && typeof style.mask !== "boolean") {
17290
+ (0, import_errors.throwBadRequest)(`flowSurfaces ${actionName} AI employee settings.style.mask must be a boolean`);
17291
+ }
17292
+ }
17293
+ props.style = import_lodash.default.merge(
17294
+ {},
17295
+ import_lodash.default.cloneDeep(AI_EMPLOYEE_DEFAULT_STYLE),
17296
+ import_lodash.default.isPlainObject(currentProps.style) ? import_lodash.default.pick(import_lodash.default.cloneDeep(currentProps.style), AI_EMPLOYEE_STYLE_PUBLIC_KEYS) : {},
17297
+ import_lodash.default.isPlainObject(style) ? import_lodash.default.pick(import_lodash.default.cloneDeep(style), AI_EMPLOYEE_STYLE_PUBLIC_KEYS) : {}
17298
+ );
17299
+ }
17300
+ return {
17301
+ props,
17302
+ stepParams
17303
+ };
17304
+ }
17305
+ async resolveAIEmployeeActionSelfUid(actionNode, transaction) {
17306
+ const parentUid = String((actionNode == null ? void 0 : actionNode.parentId) || "").trim() || ((actionNode == null ? void 0 : actionNode.uid) ? await this.locator.findParentUid(actionNode.uid, transaction).catch(() => "") : "");
17307
+ if (!parentUid) {
17308
+ return actionNode == null ? void 0 : actionNode.uid;
17309
+ }
17310
+ const parentNode = await this.repository.findModelById(parentUid, {
17311
+ transaction,
17312
+ includeAsyncNode: true
17313
+ });
17314
+ if (["TableActionsColumnModel", "ListItemModel", "GridCardItemModel"].includes(String((parentNode == null ? void 0 : parentNode.use) || ""))) {
17315
+ const ownerUid = String((parentNode == null ? void 0 : parentNode.parentId) || "").trim() || ((parentNode == null ? void 0 : parentNode.uid) ? await this.locator.findParentUid(parentNode.uid, transaction).catch(() => "") : "");
17316
+ return ownerUid || parentUid;
17317
+ }
17318
+ return parentUid;
17319
+ }
17320
+ async configureActionNode(target, use, changes, options) {
17321
+ const currentNode = options.current || (target.uid ? await this.repository.findModelById(target.uid, {
17322
+ transaction: options.transaction,
17323
+ includeAsyncNode: true
17324
+ }) : null);
17325
+ changes = await this.normalizeActionPanelActionChanges(changes, options);
17326
+ const allowedKeys = (0, import_configure_options.getConfigureOptionKeysForUse)(use);
17327
+ (0, import_service_utils.assertSupportedSimpleChanges)("action", changes, allowedKeys);
17328
+ if (this.isAIEmployeeActionUse(use)) {
17329
+ const aiEmployeeSettingsPayload = await this.normalizeAIEmployeeActionPublicSettings(
17330
+ "configure action",
17331
+ changes,
17332
+ {
17333
+ transaction: options.transaction,
17334
+ enabledPackages: options.enabledPackages || await this.resolveEnabledPluginPackages(options),
17335
+ current: currentNode,
17336
+ currentRoles: options.currentRoles,
17337
+ selfUid: await this.resolveAIEmployeeActionSelfUid(currentNode, options.transaction),
17338
+ promptContext: {
17339
+ kind: "target",
17340
+ targetUid: (currentNode == null ? void 0 : currentNode.uid) || target.uid
17341
+ }
17342
+ }
17343
+ );
17344
+ const settingsValues = { target };
17345
+ if (Object.keys(aiEmployeeSettingsPayload.props).length) {
17346
+ settingsValues.props = aiEmployeeSettingsPayload.props;
17347
+ }
17348
+ if (Object.keys(aiEmployeeSettingsPayload.stepParams).length) {
17349
+ settingsValues.stepParams = aiEmployeeSettingsPayload.stepParams;
17350
+ }
17351
+ return this.updateSettings(settingsValues, {
17352
+ ...options,
17353
+ openViewActionName: options.openViewActionName || "configure action",
17354
+ popupTemplateHostUid: target.uid,
17355
+ allowAIEmployeeInternalProps: true
17356
+ });
17357
+ }
17358
+ const normalizedDefaultFilter = (0, import_service_utils.hasOwnDefined)(changes, "defaultFilter") ? this.normalizeFilterActionDefaultFilterValue(changes.defaultFilter) : void 0;
17359
+ const stepParams = {};
17360
+ if ((0, import_service_utils.hasDefinedValue)(changes, ["title", "tooltip", "icon", "type", "danger", "color", "linkageRules"])) {
17361
+ stepParams.buttonSettings = {
17362
+ ...(0, import_service_utils.hasDefinedValue)(changes, ["title", "tooltip", "icon", "type", "danger", "color"]) ? {
17363
+ general: (0, import_service_utils.buildDefinedPayload)({
17364
+ title: changes.title,
17365
+ tooltip: changes.tooltip,
17366
+ icon: changes.icon,
17367
+ type: changes.type,
17368
+ danger: changes.danger,
17369
+ color: changes.color
17370
+ })
17371
+ } : {},
17372
+ ...(0, import_service_utils.hasOwnDefined)(changes, "linkageRules") ? { linkageRules: { value: changes.linkageRules } } : {}
17373
+ };
17374
+ }
17375
+ if ((0, import_service_utils.hasOwnDefined)(changes, "filterableFieldNames") || (0, import_service_utils.hasOwnDefined)(changes, "defaultFilter")) {
17376
+ if (use !== "FilterActionModel") {
17377
+ (0, import_errors.throwBadRequest)(`flowSurfaces configure action '${use}' does not support filterableFieldNames/defaultFilter`);
17378
+ }
17379
+ stepParams.filterSettings = (0, import_service_utils.buildDefinedPayload)({
17380
+ ...(0, import_service_utils.hasOwnDefined)(changes, "filterableFieldNames") ? {
17381
+ filterableFieldNames: {
17382
+ filterableFieldNames: import_lodash.default.cloneDeep(changes.filterableFieldNames)
17383
+ }
17384
+ } : {},
17385
+ ...(0, import_service_utils.hasOwnDefined)(changes, "defaultFilter") ? {
17386
+ defaultFilter: {
17387
+ defaultFilter: normalizedDefaultFilter
17388
+ }
17389
+ } : {}
17390
+ });
17391
+ }
17392
+ if ((0, import_service_utils.hasOwnDefined)(changes, "approvalReturn")) {
17393
+ if (use !== "ProcessFormReturnModel") {
17394
+ (0, import_errors.throwBadRequest)(`flowSurfaces configure action '${use}' does not support approvalReturn`);
17395
+ }
17396
+ import_lodash.default.set(
17397
+ stepParams,
17398
+ ["clickSettings", "saveResource", "approvalReturnNodeSettings"],
17399
+ import_lodash.default.cloneDeep(changes.approvalReturn || {})
17400
+ );
15774
17401
  }
15775
17402
  if ((0, import_service_utils.hasOwnDefined)(changes, "assigneesScope")) {
15776
17403
  if (!APPROVAL_REASSIGN_ACTION_USES.has(use)) {
@@ -17019,7 +18646,8 @@ class FlowSurfacesService {
17019
18646
  }
17020
18647
  resolveRecordActionContextOwner(ancestors) {
17021
18648
  const currentNode = ancestors[0];
17022
- if (!String((currentNode == null ? void 0 : currentNode.use) || "").endsWith("ActionModel")) {
18649
+ const currentUse = String((currentNode == null ? void 0 : currentNode.use) || "").trim();
18650
+ if (!currentUse.endsWith("ActionModel") && !import_node_use_sets.ACTION_BUTTON_USES.has(currentUse)) {
17023
18651
  return null;
17024
18652
  }
17025
18653
  return ancestors.slice(1).find((node) => (0, import_action_scope.getActionContainerScope)(node == null ? void 0 : node.use) === "record") || null;
@@ -17270,11 +18898,12 @@ class FlowSurfacesService {
17270
18898
  };
17271
18899
  }
17272
18900
  getCollection(dataSourceKey, collectionName) {
17273
- var _a, _b, _c, _d, _e;
18901
+ var _a, _b, _c, _d, _e, _f, _g, _h;
17274
18902
  const normalizedDataSourceKey = dataSourceKey || "main";
17275
- const dataSourceManager = this.plugin.app.dataSourceManager;
17276
- const dataSource = (_a = dataSourceManager == null ? void 0 : dataSourceManager.get) == null ? void 0 : _a.call(dataSourceManager, normalizedDataSourceKey);
17277
- return ((_c = (_b = dataSource == null ? void 0 : dataSource.collectionManager) == null ? void 0 : _b.getCollection) == null ? void 0 : _c.call(_b, collectionName)) || ((_e = (_d = this.plugin.app.db) == null ? void 0 : _d.getCollection) == null ? void 0 : _e.call(_d, collectionName));
18903
+ const app = (_a = this.plugin) == null ? void 0 : _a.app;
18904
+ const dataSourceManager = app == null ? void 0 : app.dataSourceManager;
18905
+ const dataSource = (_b = dataSourceManager == null ? void 0 : dataSourceManager.get) == null ? void 0 : _b.call(dataSourceManager, normalizedDataSourceKey);
18906
+ return ((_d = (_c = dataSource == null ? void 0 : dataSource.collectionManager) == null ? void 0 : _c.getCollection) == null ? void 0 : _d.call(_c, collectionName)) || ((_f = (_e = app == null ? void 0 : app.db) == null ? void 0 : _e.getCollection) == null ? void 0 : _f.call(_e, collectionName)) || ((_h = (_g = this.db) == null ? void 0 : _g.getCollection) == null ? void 0 : _h.call(_g, collectionName));
17278
18907
  }
17279
18908
  normalizeKanbanFieldNameInput(value, context, options = {}) {
17280
18909
  if (import_lodash.default.isUndefined(value)) {