@acorex/connectivity 21.0.0-beta.3 → 21.0.0-beta.4

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 (17) hide show
  1. package/fesm2022/{acorex-connectivity-mock-acorex-connectivity-mock-BvDCXP5M.mjs → acorex-connectivity-mock-acorex-connectivity-mock-BwFZQ1Xw.mjs} +1056 -664
  2. package/fesm2022/acorex-connectivity-mock-acorex-connectivity-mock-BwFZQ1Xw.mjs.map +1 -0
  3. package/fesm2022/{acorex-connectivity-mock-assign-to-manager.activity-DQRHQ_jG.mjs → acorex-connectivity-mock-assign-to-manager.activity-BgaXGmcT.mjs} +2 -2
  4. package/fesm2022/{acorex-connectivity-mock-assign-to-manager.activity-DQRHQ_jG.mjs.map → acorex-connectivity-mock-assign-to-manager.activity-BgaXGmcT.mjs.map} +1 -1
  5. package/fesm2022/{acorex-connectivity-mock-chat-generate-image.command-D_2bFiuO.mjs → acorex-connectivity-mock-chat-generate-image.command-IUvQRJU0.mjs} +2 -2
  6. package/fesm2022/{acorex-connectivity-mock-chat-generate-image.command-D_2bFiuO.mjs.map → acorex-connectivity-mock-chat-generate-image.command-IUvQRJU0.mjs.map} +1 -1
  7. package/fesm2022/{acorex-connectivity-mock-chat-synthesize-speech.command-CWK6lBgb.mjs → acorex-connectivity-mock-chat-synthesize-speech.command-DE8YU17E.mjs} +2 -2
  8. package/fesm2022/{acorex-connectivity-mock-chat-synthesize-speech.command-CWK6lBgb.mjs.map → acorex-connectivity-mock-chat-synthesize-speech.command-DE8YU17E.mjs.map} +1 -1
  9. package/fesm2022/{acorex-connectivity-mock-chat-transcribe-speech.command-B1PpdDkQ.mjs → acorex-connectivity-mock-chat-transcribe-speech.command-Cr0QRiqr.mjs} +2 -2
  10. package/fesm2022/{acorex-connectivity-mock-chat-transcribe-speech.command-B1PpdDkQ.mjs.map → acorex-connectivity-mock-chat-transcribe-speech.command-Cr0QRiqr.mjs.map} +1 -1
  11. package/fesm2022/{acorex-connectivity-mock-user-roles-for-list-column.query-BSN7vEKz.mjs → acorex-connectivity-mock-user-roles-for-list-column.query-DBhWkX3w.mjs} +2 -3
  12. package/fesm2022/acorex-connectivity-mock-user-roles-for-list-column.query-DBhWkX3w.mjs.map +1 -0
  13. package/fesm2022/acorex-connectivity-mock.mjs +1 -1
  14. package/package.json +2 -2
  15. package/types/acorex-connectivity-mock.d.ts +106 -97
  16. package/fesm2022/acorex-connectivity-mock-acorex-connectivity-mock-BvDCXP5M.mjs.map +0 -1
  17. package/fesm2022/acorex-connectivity-mock-user-roles-for-list-column.query-BSN7vEKz.mjs.map +0 -1
@@ -3,7 +3,7 @@ import * as i2$2 from '@acorex/platform/auth';
3
3
  import { AXPSessionService, AXP_PERMISSION_DEFINITION_PROVIDER, AXP_APPLICATION_LOADER, AXP_FEATURE_LOADER, AXP_PERMISSION_LOADER, AXP_TENANT_LOADER, AXP_PERMISSION_CHECKER, AXP_FEATURE_CHECKER, AXPLoginChallengeComponentBase, AXPLoginChallengeProvider, AXPAuthStrategy, AXPAuthModule, AXP_LOGIN_CHALLENGE_PROVIDER } from '@acorex/platform/auth';
4
4
  import * as i1 from '@acorex/platform/core';
5
5
  import { applyFilterArray, applySortArray, AXPDataGenerator, AXPIconLogoConfig, AXPModuleManifestRegistry, AXPActivityLogProvider, AXP_ACTIVITY_LOG_PROVIDER, AXP_DATASOURCE_DEFINITION_PROVIDER, AXPDataSourceDefinitionProviderService, AXPPlatformScope, AXP_DISTRIBUTED_EVENT_LISTENER_PROVIDER, AXPExpressionEvaluatorService, provideLazyProvider } from '@acorex/platform/core';
6
- import { AXP_ENTITY_STORAGE_BACKEND, AXPEntityStorageService, isAXPMiddlewareAbortError, AXPEntityResolver, AXP_ENTITY_DEFINITION_CRUD_SERVICE, AXPEntityService, AXP_ENTITY_DEFINITION_LOADER, AXPMiddlewareAbortError, AXP_DATA_SEEDER_TOKEN, AXP_ENTITY_STORAGE_MIDDLEWARE, AXPEntityDefinitionRegistryService, eventDispatchMiddleware, AXPDataSeederService } from '@acorex/platform/layout/entity';
6
+ import { AXP_ENTITY_STORAGE_BACKEND, AXPEntityStorageService, isAXPMiddlewareAbortError, AXPEntityResolver, collectEntityQuickSearchFieldPaths, AXP_ENTITY_DEFINITION_CRUD_SERVICE, AXPEntityService, AXP_ENTITY_DEFINITION_LOADER, AXPMiddlewareAbortError, AXP_DATA_SEEDER_TOKEN, AXP_ENTITY_STORAGE_MIDDLEWARE, AXPEntityDefinitionRegistryService, eventDispatchMiddleware, AXPDataSeederService } from '@acorex/platform/layout/entity';
7
7
  import * as i0 from '@angular/core';
8
8
  import { InjectionToken, inject, Injectable, NgModule, isDevMode, Injector, Inject, signal, Component } from '@angular/core';
9
9
  import { AXP_MENU_PROVIDER, AXPFileStorageService, AXPSettingsService, AXPSystemStatusType, AXPAppVersionService, AXPFileStorageStatus, AXVChangeType as AXVChangeType$1, AXP_SEARCH_PROVIDER, AXPLockService, AXPVersioningService, AXPSystemStatuses, AXPStatusDefinitionProviderService } from '@acorex/platform/common';
@@ -16,7 +16,7 @@ import * as i2$1 from '@acorex/core/translation';
16
16
  import { resolveMultiLanguageString, createMultiLanguageString, AXTranslationService, AXTranslationModule } from '@acorex/core/translation';
17
17
  import { AXP_WIDGET_DEFINITION_PROVIDER, AXPWidgetRegistryService, AXPWidgetsCatalog } from '@acorex/platform/layout/widget-core';
18
18
  import { providePropertiesFromFactory } from '@acorex/platform/domain';
19
- import { RootConfig, axpAiChatMessageGetText, normalizeAiToolCommandArgs, AIMANAGEMENT_CHAT_GENERATE_IMAGE_COMMAND_KEY, AIMANAGEMENT_CHAT_TRANSCRIBE_SPEECH_COMMAND_KEY, AIMANAGEMENT_CHAT_SYNTHESIZE_SPEECH_COMMAND_KEY, axpAiSupervisorAgentToolName, axpAiChatToolResultBodyJson, getAiChatCommandLlmParametersOverride, axpAiChatMessageIsDelegatedReflectionExcluded, axpAiChatMessagesFromProviderAssistant, AXPAI_DOCUMENT_VISION_DEFAULT_USER_INSTRUCTION, AXPAiManagementSettings, axpAiChatToolOrAgentResultBodyJson, AXPAiChatToolRunContextService, modelRowHasPurpose, AXPAiEngine, isChatPurposeModelRow, AXPAI_DOCUMENT_VISION_EXTRACTION_SYSTEM, axpAiChatTextMessage, AXPAI_ENGINE_DEFAULT_MAX_STEPS, axpAiCoercePlanningAssistantTextToThink, axpAiParseSupervisorAgentToolName, axpAiChatToolResultMessage, axpAiNormalizeHandlerResultToToolBody, axpAiChatAgentResultMessage, AXPAI_DELEGATED_AGENT_DEFAULT_MAX_STEPS, axpAiMergePlainAssistantTextTurn, axpAiPruneAssistantPiecesToFirstToolOnly, axpAiChatDelegatedReflectionAssistantMessage, AXPAiAssistChatModelCatalogService, axpAiAssistInitialMessagesToTranscript } from '@acorex/modules/ai-management';
19
+ import { RootConfig, axpAiChatMessageGetText, normalizeAiToolCommandArgs, AIMANAGEMENT_CHAT_GENERATE_IMAGE_COMMAND_KEY, AIMANAGEMENT_CHAT_TRANSCRIBE_SPEECH_COMMAND_KEY, AIMANAGEMENT_CHAT_SYNTHESIZE_SPEECH_COMMAND_KEY, axpAiSupervisorAgentToolName, axpAiChatToolResultBodyJson, getAiChatCommandLlmParametersOverride, axpAiChatMessagesFromProviderAssistant, AXPAI_DOCUMENT_VISION_DEFAULT_USER_INSTRUCTION, AXPAiManagementSettings, axpAiChatToolOrAgentResultBodyJson, AXPAiChatToolRunContextService, modelRowHasPurpose, AXPAiEngine, isChatPurposeModelRow, AXPAI_DOCUMENT_VISION_EXTRACTION_SYSTEM, axpAiChatTextMessage, AXPAI_ENGINE_DEFAULT_MAX_STEPS, axpAiCoercePlanningAssistantTextToThink, axpAiParseSupervisorAgentToolName, axpAiChatToolResultMessage, axpAiNormalizeHandlerResultToToolBody, axpAiChatAgentResultMessage, axpAiParseDelegatedAgentResultSegmentsFromUnknown, AXPAI_DELEGATED_AGENT_DEFAULT_MAX_STEPS, axpAiMergePlainAssistantTextTurn, axpAiPruneAssistantPiecesToFirstToolOnly, axpAiChatDelegatedReflectionAssistantMessage, axpAiDelegatedSubTranscriptAppendFileArtifactFromToolResults, axpAiCollectDelegatedAgentOutcomeResponses, axpAiDelegatedAgentOutcomeResponsesPlainText, axpAiChatMessageIsDelegatedReflectionExcluded, AXPAiAssistChatModelCatalogService, axpAiAssistInitialMessagesToTranscript } from '@acorex/modules/ai-management';
20
20
  import { RootConfig as RootConfig$1 } from '@acorex/modules/platform-management';
21
21
  import { RootConfig as RootConfig$2, AXMPermissionsKeys, AXMApplicationService, AXMEditionService } from '@acorex/modules/application-management';
22
22
  import { AXMAssetManagementFeatureKeys, RootConfig as RootConfig$4, AXMAssetStatus } from '@acorex/modules/asset-management';
@@ -35,10 +35,10 @@ import { RootConfig as RootConfig$8 } from '@acorex/modules/calendar-management'
35
35
  import { AXFileService } from '@acorex/core/file';
36
36
  import { RootConfig as RootConfig$9, resolveTextTemplateLocalizedString, replaceTextTemplatePlaceholders, AXC_TEXT_TEMPLATE_RENDER_COMMAND_KEY } from '@acorex/modules/content-management';
37
37
  import { conversationSharedStorage, axConversationIndexedDbStorage, AXConversationAiResponderService } from '@acorex/components/conversation2';
38
- import { AXMChatUserApi, axmIsAssistPeerParticipant, AXMChatRealtimeApi, AXMChatConversationApi, AXMChatMessageApi, AXMChatManagementService, AXMChatRealtimeService, AXMCommentManagementService, AXMCommentRealtimeService, RootConfig as RootConfig$a } from '@acorex/modules/conversation';
39
- import { Observable, filter, take, map, throttleTime } from 'rxjs';
40
- import { AXToastService } from '@acorex/components/toast';
38
+ import { AXMChatConversationApi, AXMChatMessageApi, axmExtractAssistFinalDeliverableFromTranscript, AXMChatRealtimeApi, AXMChatUserApi, axmIsAssistPeerParticipant, AXMChatManagementService, AXMChatRealtimeService, AXMCommentManagementService, AXMCommentRealtimeService, RootConfig as RootConfig$a } from '@acorex/modules/conversation';
41
39
  import { AXMNotificationEntityService, RootConfig as RootConfig$p, AXMNotificationEntityServiceImpl, AXMNotificationRealtimeService, NOTIFICATION_MANAGEMENT_EMAIL_SEND_COMMAND_KEY } from '@acorex/modules/notification-management';
40
+ import { AXToastService } from '@acorex/components/toast';
41
+ import { Observable, filter, pairwise, map, merge, take, throttleTime } from 'rxjs';
42
42
  import { RootConfig as RootConfig$b } from '@acorex/modules/customer-management';
43
43
  import { RootConfig as RootConfig$c } from '@acorex/modules/dashboard-management';
44
44
  import { AXDataSource } from '@acorex/cdk/common';
@@ -813,69 +813,6 @@ function parseEntityStorageQueryRequest(raw) {
813
813
  };
814
814
  }
815
815
  //#endregion
816
- //#region ---- Quick search: schema-driven field paths ----
817
- const NON_TEXT_DATATYPES = new Set([
818
- 'number',
819
- 'integer',
820
- 'int',
821
- 'long',
822
- 'float',
823
- 'double',
824
- 'decimal',
825
- 'money',
826
- 'currency',
827
- 'boolean',
828
- 'bool',
829
- 'date',
830
- 'datetime',
831
- 'time',
832
- 'object',
833
- 'array',
834
- 'json',
835
- 'image',
836
- 'file',
837
- 'binary',
838
- ]);
839
- /**
840
- * Whether {@link AXPEntity} property likely stores free text worth a `contains` quick-search clause.
841
- */
842
- function isTextLikeDataType(dataType) {
843
- const dt = (dataType ?? 'string').toLowerCase().trim();
844
- if (!dt || NON_TEXT_DATATYPES.has(dt)) {
845
- return false;
846
- }
847
- return true;
848
- }
849
- /**
850
- * Derives lodash-get paths for quick search from the entity definition: string-like property names
851
- * plus lookup `expose[].target` paths (e.g. `brand.title`).
852
- */
853
- function collectQuickSearchFieldPathsFromEntityDefinition(entity) {
854
- if (!entity?.properties?.length) {
855
- return [];
856
- }
857
- const paths = new Set();
858
- for (const p of entity.properties) {
859
- if (isTextLikeDataType(p.schema?.dataType)) {
860
- paths.add(p.name);
861
- }
862
- const opts = p.schema?.interface?.options;
863
- const expose = opts?.['expose'];
864
- if (!Array.isArray(expose)) {
865
- continue;
866
- }
867
- for (const row of expose) {
868
- if (row && typeof row === 'object' && typeof row.target === 'string') {
869
- const t = (row.target).trim();
870
- if (t) {
871
- paths.add(t);
872
- }
873
- }
874
- }
875
- }
876
- return [...paths];
877
- }
878
- //#endregion
879
816
  //#region ---- AI-friendly quick search → standard filter ----
880
817
  /** Fields commonly present across entities; always included for quickSearch. */
881
818
  const ENTITY_STORAGE_QUICK_SEARCH_BASE_FIELD_PATHS = ['id', 'code', 'title', 'name', 'shortName'];
@@ -996,7 +933,7 @@ class AXCEntityStorageQueryQuery {
996
933
  const def = moduleName && entityNameOnly
997
934
  ? await this.entityResolver.get(moduleName, entityNameOnly)
998
935
  : null;
999
- const fromSchema = collectQuickSearchFieldPathsFromEntityDefinition(def);
936
+ const fromSchema = await collectEntityQuickSearchFieldPaths(def, (m, n) => this.entityResolver.get(m, n));
1000
937
  const explicit = normalizeQuickSearchFieldPaths(input.quickSearchFieldPaths);
1001
938
  const quickPaths = [...new Set([...fromSchema, ...explicit])];
1002
939
  merged = mergeQuickSearchIntoRequest(request, input.quickSearch, quickPaths);
@@ -6455,6 +6392,49 @@ const COMMAND_REGISTRY_SEED = [
6455
6392
  ]
6456
6393
  }
6457
6394
  },
6395
+ {
6396
+ "id": "cmd_40590ed17cec",
6397
+ "definition": {
6398
+ "name": "axe-document:dialog.metadata-ai-fill",
6399
+ "active": true,
6400
+ "description": "Input for the metadata AI fill command (attachment dialog footer).",
6401
+ "inputOptionDefinitions": [
6402
+ {
6403
+ "name": "dialogRef",
6404
+ "title": "dialogRef",
6405
+ "interface": {
6406
+ "name": "large-text-editor",
6407
+ "title": "dialogRef",
6408
+ "options": {
6409
+ "readonly": false
6410
+ }
6411
+ },
6412
+ "validations": [
6413
+ {
6414
+ "rule": "required"
6415
+ }
6416
+ ]
6417
+ },
6418
+ {
6419
+ "name": "integration",
6420
+ "title": "integration",
6421
+ "interface": {
6422
+ "name": "large-text-editor",
6423
+ "title": "integration",
6424
+ "options": {
6425
+ "readonly": false
6426
+ }
6427
+ },
6428
+ "validations": [
6429
+ {
6430
+ "rule": "required"
6431
+ }
6432
+ ]
6433
+ }
6434
+ ],
6435
+ "outputOptionDefinitions": []
6436
+ }
6437
+ },
6458
6438
  {
6459
6439
  "id": "cmd_af7c717c9802",
6460
6440
  "definition": {
@@ -6715,6 +6695,44 @@ const COMMAND_REGISTRY_SEED = [
6715
6695
  ]
6716
6696
  }
6717
6697
  },
6698
+ {
6699
+ "id": "cmd_49c15ef1b9cd",
6700
+ "definition": {
6701
+ "name": "Entity:List",
6702
+ "active": true,
6703
+ "description": "Platform command WorkOrderListCommand. Declared in modules/maintenance-management/src/lib/features/commands/work-order-list-command.ts. Use the input parameters when invoking this command (e.g. from automation or AI tools).",
6704
+ "inputOptionDefinitions": [
6705
+ {
6706
+ "name": "entity",
6707
+ "title": "entity",
6708
+ "interface": {
6709
+ "name": "text-editor",
6710
+ "title": "entity",
6711
+ "options": {
6712
+ "readonly": false
6713
+ }
6714
+ },
6715
+ "validations": [
6716
+ {
6717
+ "rule": "required"
6718
+ }
6719
+ ]
6720
+ },
6721
+ {
6722
+ "name": "conditions",
6723
+ "title": "conditions",
6724
+ "interface": {
6725
+ "name": "large-text-editor",
6726
+ "title": "conditions",
6727
+ "options": {
6728
+ "readonly": false
6729
+ }
6730
+ }
6731
+ }
6732
+ ],
6733
+ "outputOptionDefinitions": []
6734
+ }
6735
+ },
6718
6736
  {
6719
6737
  "id": "cmd_3f20719e4e46",
6720
6738
  "definition": {
@@ -11641,6 +11659,103 @@ const QUERY_REGISTRY_SEED = [
11641
11659
  ]
11642
11660
  }
11643
11661
  },
11662
+ {
11663
+ "id": "qry_926e7f5cf9ed",
11664
+ "definition": {
11665
+ "name": "PlatformManagement:ListPlatformNavigationForAi",
11666
+ "active": true,
11667
+ "description": "Returns a flattened snapshot of sidebar / shell menus **after middleware** — resolved titles, hierarchy paths, and router paths. Use together with **`PlatformManagement:ListRegisteredEntities`** to answer “where do I…” (navigation) vs “what fields does…” (entities). Prefer rows with a **`path`** for clickable destinations. Optional **`quickSearch`** narrows titles, translation keys, `menuName`, and paths. Output is capped (`limit`): set higher only when pagination is unavoidable.",
11668
+ "inputOptionDefinitions": [
11669
+ {
11670
+ "name": "quickSearch",
11671
+ "title": "Quick filter",
11672
+ "interface": {
11673
+ "name": "text-editor",
11674
+ "title": "Quick filter",
11675
+ "options": {}
11676
+ },
11677
+ "description": "Optional plain-text substring filter (titles, `@scope:key` values, paths, breadcrumbs). Omit to list the capped full visible tree snapshot."
11678
+ },
11679
+ {
11680
+ "name": "limit",
11681
+ "title": "Max rows",
11682
+ "interface": {
11683
+ "name": "text-editor",
11684
+ "title": "Max rows",
11685
+ "options": {
11686
+ "readonly": false
11687
+ }
11688
+ },
11689
+ "description": "Soft cap **40–500** after filtering (default **300**). Omit for default; raises only payload size."
11690
+ }
11691
+ ],
11692
+ "outputOptionDefinitions": [
11693
+ {
11694
+ "name": "success",
11695
+ "title": "Success",
11696
+ "interface": {
11697
+ "name": "toggle-editor",
11698
+ "title": "Success",
11699
+ "options": {}
11700
+ },
11701
+ "description": "Whether the menu snapshot succeeded."
11702
+ },
11703
+ {
11704
+ "name": "matchStatus",
11705
+ "title": "Match status",
11706
+ "interface": {
11707
+ "name": "text-editor",
11708
+ "title": "Match status",
11709
+ "options": {}
11710
+ },
11711
+ "description": "`catalog` — entire visible tree baseline; `filtered` — applied quickSearch; `empty` — quickSearch removed every row."
11712
+ },
11713
+ {
11714
+ "name": "navigation",
11715
+ "title": "Navigation rows",
11716
+ "interface": {
11717
+ "name": "large-text-editor",
11718
+ "title": "Navigation rows",
11719
+ "options": {}
11720
+ },
11721
+ "description": "Flattened rows: **`title`**, **`hierarchyPath`** (breadcrumb), **`path`** route when navigable."
11722
+ },
11723
+ {
11724
+ "name": "truncated",
11725
+ "title": "Truncated",
11726
+ "interface": {
11727
+ "name": "toggle-editor",
11728
+ "title": "Truncated",
11729
+ "options": {}
11730
+ },
11731
+ "description": "When true, rows existed beyond **`limit`; refine `quickSearch` or raise `limit`."
11732
+ },
11733
+ {
11734
+ "name": "error",
11735
+ "title": "Error",
11736
+ "interface": {
11737
+ "name": "text-editor",
11738
+ "title": "Error",
11739
+ "options": {}
11740
+ },
11741
+ "description": "Present when success is false."
11742
+ }
11743
+ ],
11744
+ "catalogTitle": "List platform navigation (for AI grounding)",
11745
+ "executionMode": "frontend",
11746
+ "aiMetadataJson": "{\n \"shortDescription\": \"Flattened visible menu titles + breadcrumbs + router paths — ground “how do I…” navigation answers before inventing URLs.\",\n \"tags\": [\n \"navigation\",\n \"menu\",\n \"breadcrumb\",\n \"help\",\n \"how-to\",\n \"platform-ui\"\n ],\n \"usage\": {\n \"whenToUse\": [\n \"User asks where to configure something, open a module list, create users, navigate to definitions, etc.\",\n \"Before asserting a sidebar path exists — cite `hierarchyPath` and concrete `path` from tool rows.\"\n ],\n \"avoidWhen\": [\n \"You only need Module.Entity schemas — use **`PlatformManagement:ListRegisteredEntities`** instead.\"\n ],\n \"followUpTools\": [\n \"PlatformManagement:ListRegisteredEntities\"\n ]\n },\n \"contracts\": {\n \"provides\": [\n \"menuNavigationGrounding\"\n ],\n \"guarantees\": [\n \"Only entries visible **after menu middleware** are returned (effective shell navigation).\",\n \"Rows are flattened pre-order DFS; breadcrumbs include every ancestor title resolved for the locale.\"\n ]\n },\n \"safety\": {\n \"kind\": \"read-only\",\n \"sideEffects\": false,\n \"requiresConfirmation\": false\n },\n \"performance\": {\n \"cost\": \"low\",\n \"cacheable\": false\n }\n}",
11747
+ "capabilities": [
11748
+ "ai"
11749
+ ],
11750
+ "categories": [
11751
+ {
11752
+ "name": "platform",
11753
+ "order": 1,
11754
+ "title": "Platform"
11755
+ }
11756
+ ]
11757
+ }
11758
+ },
11644
11759
  {
11645
11760
  "id": "qry_7fc1db5874d8",
11646
11761
  "definition": {
@@ -11843,7 +11958,7 @@ const QUERY_REGISTRY_SEED = [
11843
11958
  "title": "AI agent scope",
11844
11959
  "options": {}
11845
11960
  },
11846
- "description": "Required. Must match the calling delegated agent catalog `name`: widget-form-layout | widget-chart-layout | widget-dashboard-layout. Lists and detail lookups are filtered to that specialist scope.",
11961
+ "description": "Required. Must match the calling delegated agent catalog `name`: widget-form-layout | widget-chart-layout | widget-follow-up-chips-layout. Lists and detail lookups are filtered to that specialist scope.",
11847
11962
  "validations": [
11848
11963
  {
11849
11964
  "rule": "required"
@@ -12769,7 +12884,7 @@ const WIDGET_CATALOG_SEED = [
12769
12884
  definition: {
12770
12885
  name: 'rate-picker-editor',
12771
12886
  active: true,
12772
- metadataJson: '{\n "name": "rate-picker-editor",\n "title": "@platform-layout-widgets:widgets.rate-picker-editor.title",\n "description": "@platform-layout-widgets:widgets.rate-picker-editor.description",\n "icon": "fa-light fa-star",\n "categories": {\n "name": "editor",\n "order": 2,\n "title": "@platform-layout-widgets:categories.editor.title"\n },\n "subCategory": {\n "name": "editor-numeric",\n "order": 2,\n "title": "@platform-layout-widgets:subcategories.editor-numeric.title"\n },\n "groups": [\n "form-element"\n ],\n "defaultFilterWidgetName": "number-filter",\n "type": "editor",\n "inputs": [\n {\n "name": "name",\n "title": "Name",\n "interface": {\n "name": "text-editor"\n }\n },\n {\n "name": "path",\n "title": "Data Path",\n "interface": {\n "name": "text-editor"\n }\n },\n {\n "name": "disabled",\n "title": "Disabled",\n "interface": {\n "name": "toggle-editor"\n }\n },\n {\n "name": "readonly",\n "title": "Readonly",\n "description": "Inline createBooleanProperty path options.readonly; edit passes to ax-rate-picker; view/column force readonly true.",\n "interface": {\n "name": "toggle-editor"\n }\n },\n {\n "name": "max",\n "title": "Max Value",\n "description": "Inline createNumberProperty path options.max; default 5 in config; used for ax-rate-picker [max] and tooltip text.",\n "interface": {\n "name": "number-editor"\n }\n },\n {\n "name": "width",\n "title": "Width",\n "description": "cloneProperty(AXP_TABLE_COLUMN_WIDTH_PROPERTY) with default 150px in config; path options.width.",\n "interface": {\n "name": "text-editor"\n }\n },\n {\n "name": "requiredValidation",\n "title": "Required",\n "interface": {\n "name": "required-validation"\n }\n }\n ],\n "outputs": [\n {\n "name": "boundValue",\n "title": "Rating",\n "description": "number | null from ngModel; internalValue uses getValue() ?? null.",\n "interface": {\n "name": "number-editor"\n }\n }\n ],\n "ai": {\n "tags": [\n "editor",\n "rating",\n "stars"\n ],\n "usage": {\n "whenToUse": [\n "Star (or step) rating up to options.max with optional disabled/readonly states."\n ],\n "avoidWhen": [\n "Continuous percentage — progress-bar-editor."\n ]\n },\n "renderSurfaces": [\n {\n "mode": "edit",\n "summary": "AXPValueWidgetComponent<number | null>: ax-rate-picker ngModel internalValue; validation rules from base."\n },\n {\n "mode": "view",\n "summary": "AXPValueWidgetComponent<number | null>: readonly ax-rate-picker; title tooltip `${value} / ${max()}`."\n },\n {\n "mode": "column",\n "summary": "AXPColumnWidgetComponent<number | null>: same readonly picker when rawValue defined; else ---."\n },\n {\n "mode": "designer",\n "summary": "Reuses rate-picker-widget-edit."\n }\n ],\n "instruction": "View ignores options.readonly for display mode (always readonly true). Column host uses ax-xs ax-flex."\n }\n}',
12887
+ metadataJson: '{\n "name": "rate-picker-editor",\n "title": "@platform-layout-widgets:widgets.rate-picker-editor.title",\n "description": "@platform-layout-widgets:widgets.rate-picker-editor.description",\n "icon": "fa-light fa-star",\n "categories": {\n "name": "editor",\n "order": 2,\n "title": "@platform-layout-widgets:categories.editor.title"\n },\n "subCategory": {\n "name": "editor-numeric",\n "order": 2,\n "title": "@platform-layout-widgets:subcategories.editor-numeric.title"\n },\n "groups": [\n "form-element"\n ],\n "defaultFilterWidgetName": "number-filter",\n "type": "editor",\n "inputs": [\n {\n "name": "name",\n "title": "Name",\n "interface": {\n "name": "text-editor"\n }\n },\n {\n "name": "path",\n "title": "Data Path",\n "interface": {\n "name": "text-editor"\n }\n },\n {\n "name": "disabled",\n "title": "Disabled",\n "interface": {\n "name": "toggle-editor"\n }\n },\n {\n "name": "readonly",\n "title": "Readonly",\n "description": "Inline createBooleanProperty path options.readonly; edit passes to ax-rate-picker; view/column force readonly true.",\n "interface": {\n "name": "toggle-editor"\n }\n },\n {\n "name": "max",\n "title": "Max Value",\n "description": "Inline createNumberProperty path options.max; default 5 in config; used for ax-rate-picker [max] and tooltip text.",\n "interface": {\n "name": "number-editor"\n }\n },\n {\n "name": "width",\n "title": "Width",\n "description": "cloneProperty(AXP_TABLE_COLUMN_WIDTH_PROPERTY) with default 150px in config; path options.width.",\n "interface": {\n "name": "text-editor"\n }\n },\n {\n "name": "requiredValidation",\n "title": "Required",\n "interface": {\n "name": "required-validation"\n }\n }\n ],\n "outputs": [\n {\n "name": "boundValue",\n "title": "Rating",\n "description": "number | null from ngModel; internalValue uses getValue() ?? null.",\n "interface": {\n "name": "number-editor"\n }\n }\n ],\n "ai": {\n "tags": [\n "editor",\n "rating",\n "stars"\n ],\n "usage": {\n "whenToUse": [\n "Star (or step) rating up to options.max with optional disabled/readonly states."\n ],\n "avoidWhen": [\n "Continuous percentage — progress-bar-editor."\n ]\n },\n "renderSurfaces": [\n {\n "mode": "edit",\n "summary": "AXPValueWidgetComponent<number | null>: ax-rate-picker ngModel internalValue; validation rules from base."\n },\n {\n "mode": "view",\n "summary": "AXPValueWidgetComponent<number | null>: readonly ax-rate-picker; title tooltip `${value} / ${max()}`."\n },\n {\n "mode": "column",\n "summary": "AXPColumnWidgetComponent<number | null>: same readonly picker when rawValue defined; else ---."\n },\n {\n "mode": "designer",\n "summary": "Reuses rate-picker-widget-edit."\n }\n ],\n "instruction": "View ignores options.readonly for display mode (always readonly true). Column host uses ax-xs flex."\n }\n}',
12773
12888
  catalogTitle: '@platform-layout-widgets:widgets.rate-picker-editor.title',
12774
12889
  description: '@platform-layout-widgets:widgets.rate-picker-editor.description',
12775
12890
  },
@@ -13580,6 +13695,7 @@ const AXM_AI_REGISTRY_COMMAND_NAME = {
13580
13695
  const AXM_AI_REGISTRY_QUERY_NAME = {
13581
13696
  listRegisteredEntities: 'PlatformManagement:ListRegisteredEntities',
13582
13697
  listRegisteredDataSources: 'PlatformManagement:ListRegisteredDataSources',
13698
+ listPlatformNavigationForAi: 'PlatformManagement:ListPlatformNavigationForAi',
13583
13699
  entityStorageQuery: 'ConnectivityMock:EntityStorage:Query',
13584
13700
  widgetsGetForAi: 'Widgets:GetForAI',
13585
13701
  };
@@ -13685,12 +13801,14 @@ const AXMAiAgentDocumentOcrId = 'c0000001-0000-4000-8000-000000000005';
13685
13801
  const AXMAiAgentSpeechToTextId = 'c0000001-0000-4000-8000-000000000006';
13686
13802
  /** Text-to-speech via AiManagement:ChatSynthesizeSpeech. */
13687
13803
  const AXMAiAgentTextToSpeechId = 'c0000001-0000-4000-8000-000000000007';
13804
+ /** How-to/navigation grounding: flattened menus plus entity catalog introspection — read-only queries only. */
13805
+ const AXMAiAgentPlatformHelpId = 'c0000001-0000-4000-8000-000000000013';
13806
+ /** Follow-up chip rows (`flex-layout` + `button-action`) — Widgets:GetForAI scoped to `widget-follow-up-chips-layout`. */
13807
+ const AXMAiAgentWidgetFollowUpChipsLayoutId = 'c0000001-0000-4000-8000-000000000014';
13688
13808
  /** Platform forms, chat tables, editors — Widgets:GetForAI scoped to `widget-form-layout`. */
13689
13809
  const AXMAiAgentWidgetFormLayoutId = 'c0000001-0000-4000-8000-000000000010';
13690
- /** Dashboard chart tiles (cartesian / radial / specialized) — Widgets:GetForAI scoped to `widget-chart-layout`. */
13810
+ /** Chart visualization widgets — Widgets:GetForAI scoped to `widget-chart-layout`. */
13691
13811
  const AXMAiAgentWidgetChartLayoutId = 'c0000001-0000-4000-8000-000000000011';
13692
- /** Dashboard KPI, utility, weather, clocks, shortcuts — Widgets:GetForAI scoped to `widget-dashboard-layout`. */
13693
- const AXMAiAgentWidgetDashboardLayoutId = 'c0000001-0000-4000-8000-000000000012';
13694
13812
  /**
13695
13813
  * Commerce / centralized payment guide. Catalog `name` equals Demisco `agent_uuid`
13696
13814
  * (`2a0e1e4d-ddfe-4f04-b7ba-2fd307eb5967`).
@@ -13699,11 +13817,85 @@ const AXMAiAgentCentralizedPaymentGuideId = 'c0000001-0000-4000-8000-00000000000
13699
13817
  //#endregion
13700
13818
  //#region ---- Seed rows ----
13701
13819
  const AI_AGENT_MOCK = [
13820
+ {
13821
+ id: AXMAiAgentPlatformHelpId,
13822
+ name: 'platform-help',
13823
+ title: M$17('Platform Help and Navigation', 'راهنمای پلتفرم و ناوبری'),
13824
+ description: M$17('Guides **end users** on how to use ACoreX: where to go in the app (menu discovery via **ListPlatformNavigationForAi**) and which **Module.Entity** backs a screen (via **ListRegisteredEntities**). Answers must sound **human and non-technical** unless the user asks for developer details. Read-only queries only; delegate storage/CRUD to **platform-entity**.', 'راهنمای **کاربر نهایی** برای استفاده از ACoreX: مسیر منو (**ListPlatformNavigationForAi**) و تطبیق موجودیت (**ListRegisteredEntities**). پاسخ‌ها باید **ساده و غیرفنی** باشند مگر کاربر جزئیات توسعه‌دهنده بخواهد. فقط پرس‌وجو؛ برای CRUD سرپرست **platform-entity** را واگذار می‌کند.'),
13825
+ toolIds: [],
13826
+ queryIds: [
13827
+ aiAgentQueryBinding(axcResolveQueryRegistrySeedId(AXM_AI_REGISTRY_QUERY_NAME.listPlatformNavigationForAi)),
13828
+ aiAgentQueryBinding(axcResolveQueryRegistrySeedId(AXM_AI_REGISTRY_QUERY_NAME.listRegisteredEntities)),
13829
+ ],
13830
+ systemPrompt: [
13831
+ 'You are the **platform guidance** specialist for ACoreX.',
13832
+ '',
13833
+ '## Grounding mandate (critical)',
13834
+ '- For **navigation / “how do I…” / where is X** answers: you **must** call **`PlatformManagement:ListPlatformNavigationForAi`** in that turn **before** writing numbered steps — no generic “typically you would…” guesses.',
13835
+ '- After menu rows clarify the **`Module.Entity`**, immediately fetch **`properties`** plus toolbar labels using **`PlatformManagement:ListRegisteredEntities`** with **`entityFullName`** *or* use **`PlatformManagement:ListPlatformNavigationForAi`** with **`entityFullName`** (response includes **`entityMasterUiActions`**). Prefer **exact** breadcrumbs from **`hierarchyPath`** (preserve **›**) — **one concrete path**, never vague **“A or B or C”** unless the navigation tool genuinely returned distinct matching rows.',
13836
+ '- **Never hedge toolbar labels**: do **not** write “click **New, Add**, or …”. If tools returned **`listToolbar`** / **`recordToolbar`**, cite the **`resolvedTitle`** of the **`Create`-type action** verbatim; otherwise omit button wording.',
13837
+ '- **Do not invent form fields.** To say what appears on **Create/User** flows, **`properties[].title`** from **`ListRegisteredEntities`** (**`entityFullName`**) is the sole source — if you have not fetched it, **omit “common details”** lists instead of mentioning email/fields that tools did not expose.',
13838
+ '',
13839
+ '## Tool usage',
13840
+ '- For “where do I…”, navigation, onboarding: call **`PlatformManagement:ListPlatformNavigationForAi`** first. Use **`quickSearch`** when results would be truncated. When you already know the canonical **`Module.Entity`** (e.g. `SecurityManagement.User` from **`ListRegisteredEntities`**), pass **`entityFullName`** on the same navigation call to receive **`entityMasterUiActions`** — cite those **resolved** toolbar captions (Create, Delete, View, …) instead of guessing.',
13841
+ '- For entity keys or required fields: call **`PlatformManagement:ListRegisteredEntities`** (narrow with **`entityFullName`** once you know the exact `Module.Entity`); the row includes **master toolbar actions** (**`masterUiActions`**) alongside **`properties`**.',
13842
+ '- Do **not** run entity create/update tools here — tell the supervising assistant to use **platform-entity** when the user needs inserts/updates.',
13843
+ '',
13844
+ '## Answer style — default to **end-user friendly**',
13845
+ '- Write **short, readable steps**: what to open in the sidebar or ribbon, then what to do on the page. Use everyday language.',
13846
+ '- Use **`title`** strings from navigation tool rows as the wording users recognize (breadcrumb trail in natural prose, e.g. “Administration › Security › Users”). Do **not** paste raw JSON or internal field labels such as **`hierarchyPath`** or **`path`** unless the user clearly wants **technical / IT / troubleshooting** detail.',
13847
+ '- Omit **routing URLs** (`path`) from the **main** answer. If linking would help advanced users, add **one optional line**: “Technical link (for admins): …” instead of leading with URLs.',
13848
+ '- Never label sections **“Verified navigation”** or **“Not verified”** — blend facts into the steps. If tool results lacked enough signal, admit that in **one sentence** instead of pretending. Never end with pointless offers (“**I can also help you find …**”). If navigation was empty after search, instruct the user **one** concrete refinement (e.g. reply with **exact** wording of their sidebar group for Users) instead of fluff.',
13849
+ '- If **`properties`** is available, list field hints using those **`title`** values only (**username**, **roles**, …). Otherwise **omit** field lists.',
13850
+ '- Keep lists small (about **5–7** steps max). Prefer one short paragraph plus numbered steps.',
13851
+ '- When UI labels differ slightly from tool results, trust the **`title`** from tools for spelling; explain gently if ambiguity remains.',
13852
+ '',
13853
+ '## Navigation search failures (`matchStatus`)',
13854
+ '- When **`quickSearch`** yields **`matchStatus: empty`** or no plausible row: immediately call **`PlatformManagement:ListPlatformNavigationForAi`** again with **`quickSearch` omitted** (default **`limit`**) to load the visible menu snapshot. Inspect **`navigation`** for **`title`** / **`hierarchyPath`** matching the user goal; if helpful, call again with **`quickSearch`** equal to **one substring copied from a promising row**. Do **not** stop after a single empty filter.',
13855
+ '- For **“how do I add a user”**, also call **`ListRegisteredEntities`** with **`entityFullName`**: **`SecurityManagement.User`** in parallel-style logic so you already have **`masterUiActions`** + **`properties`** even if sidebar labels are elusive.',
13856
+ '- **Only after** those retries should you apologize briefly: state that **saved menu rows contained no labeled match**, then ask **one** follow-up (**verbatim** wording of **one** sidebar item). **Banned when navigation failed**: invented example paths (“Administrative vs Security”), multi-option guesses, “places to check”, and “If you want, I can also…”.',
13857
+ ].join('\n'),
13858
+ modelEntityId: null,
13859
+ maxSteps: 18,
13860
+ },
13861
+ {
13862
+ id: AXMAiAgentWidgetFollowUpChipsLayoutId,
13863
+ name: 'widget-follow-up-chips-layout',
13864
+ title: M$17('Follow-Up Chips Agent', 'دستیار چیسپ‌های پیشنهادی'),
13865
+ description: M$17('Builds **follow-up chip** rows (**flex-layout** + **button-action**) for Conversation assist: discover option keys via scoped **Widgets:GetForAI** (`agent: widget-follow-up-chips-layout`), compose triggers that call **`methods.aiAssistFillComposerPrompt`** / **`methods.aiAssistNavigate`**, validate with **ValidateLayoutJsonForAi**. Supervisor wraps as {"type":"node","content":...}.', 'ردیف **چیسپ پیشنهادی** (**flex-layout** + **button-action**) برای دستیار مکالمه؛ کشف پارامتر با **Widgets:GetForAI** با scope چیسپ، trigger با **methods.aiAssist*** و اعتبارسنجی با **ValidateLayoutJsonForAi**؛ سرپرست خروجی را در envelope می‌پیچد.'),
13866
+ toolIds: [
13867
+ aiAgentCommandBinding(axcResolveCommandRegistrySeedId(AXM_AI_REGISTRY_COMMAND_NAME.aiFormbuilderValidateLayoutJsonForAi)),
13868
+ ],
13869
+ queryIds: [
13870
+ aiAgentQueryBinding(axcResolveQueryRegistrySeedId(AXM_AI_REGISTRY_QUERY_NAME.widgetsGetForAi), {
13871
+ agent: 'widget-follow-up-chips-layout',
13872
+ }),
13873
+ ],
13874
+ systemPrompt: [
13875
+ 'You are the **conversation follow-up chip** specialist for ACoreX assist. Your **only** successful outcome is a renderable **AXPWidgetNode** JSON describing a horizontal chip row (`flex-layout` root with `button-action` children) — no prose, no markdown fences.',
13876
+ '',
13877
+ '## Scope',
13878
+ '- **Widgets:GetForAI** lists only **`flex-layout`** and **`button-action`** for this agent (`agent: widget-follow-up-chips-layout`).',
13879
+ '- Read **`detail.structured.inputs`** for each widget before emitting `options` or `triggers`.',
13880
+ '',
13881
+ '## Composer & navigation triggers',
13882
+ "- Each **`button-action`** wires click via **`triggers`**: `{ \"event\": \"{{events.from('onClick')}}\", \"action\": \"{{methods.aiAssistFillComposerPrompt(...)}}\" }` to pre-fill the conversation composer draft, **or** `{{methods.aiAssistNavigate(...)}}` for `Router.navigateByUrl`.",
13883
+ '- Pass prompts/paths via JSON-stringified literals inside the expression exactly like other scripted layout JSON (avoid manual escaping mistakes — build from structured args).',
13884
+ '',
13885
+ '## Output contract',
13886
+ '- Output the **inner** widget root only (single **flex-layout** wrapping **button-action** chips, no `{ "type":"node" }` envelope).',
13887
+ '',
13888
+ '## Validation',
13889
+ '- You **must** call **AiFormbuilder:ValidateLayoutJsonForAi** on the draft. When **`data.valid`** is true, your **final** message is **exactly** **`data.normalizedJson`** (one parseable JSON object, no markdown fences, no extra prose).',
13890
+ ].join('\n'),
13891
+ modelEntityId: null,
13892
+ maxSteps: 14,
13893
+ },
13702
13894
  {
13703
13895
  id: AXMAiAgentPlatformEntityId,
13704
13896
  name: 'platform-entity',
13705
- title: M$17('Platform entities', 'موجودیت‌های پلتفرم'),
13706
- description: M$17('End-to-end work with platform entities: discover Module.Entity keys and field definitions, list or search stored rows, and create or update rows through the standard entity commands. Returns factual text/JSON — for tabular or form UI in chat, the supervisor should also call the **widget-form-layout** specialist; for dashboard chart tiles **widget-chart-layout**; for other dashboard tiles **widget-dashboard-layout**.', 'کار با موجودیت‌های پلتفرم: کشف کلیدهای Module.Entity و تعاریف فیلدها، فهرست یا جستجوی رکوردها، و ایجاد یا به‌روزرسانی از طریق دستورات استاندارد موجودیت. خروجی متن/JSON واقعی — برای UI جدولی در چت، سرپرست باید specialist فرم (**widget-form-layout**)، برای کاشی‌های نمودار (**widget-chart-layout**) یا سایر کاشی‌های داشبورد (**widget-dashboard-layout**) را فراخوانی کند.'),
13897
+ title: M$17('Platform Entity Agent', 'دستیار موجودیت پلتفرم'),
13898
+ description: M$17('End-to-end work with platform entities: discover Module.Entity keys and field definitions, list or search stored rows, and create or update rows through the standard entity commands. Returns factual text/JSON — for tabular or form UI in chat, the supervisor should also call the **widget-form-layout** specialist; for **charts** (bar, line, donut, gauge, funnel, heatmap) **widget-chart-layout**; for clickable follow-up chips in Conversation assist, **widget-follow-up-chips-layout**.', 'کار با موجودیت‌های پلتفرم: کشف کلیدهای Module.Entity و تعاریف فیلدها، فهرست یا جستجوی رکوردها، و ایجاد یا به‌روزرسانی از طریق دستورات استاندارد موجودیت. خروجی متن/JSON واقعی — برای UI جدولی در چت سرپرست **widget-form-layout**، برای **نمودار** (میله، خط، …) **widget-chart-layout**، و برای چیسپ پیشنهادی در مکالمه **widget-follow-up-chips-layout** را فراخوانی کند.'),
13707
13899
  toolIds: [
13708
13900
  aiAgentCommandBinding(axcResolveCommandRegistrySeedId(AXM_AI_REGISTRY_COMMAND_NAME.entityCreate)),
13709
13901
  aiAgentCommandBinding(axcResolveCommandRegistrySeedId(AXM_AI_REGISTRY_COMMAND_NAME.entityUpdate)),
@@ -13715,9 +13907,12 @@ const AI_AGENT_MOCK = [
13715
13907
  systemPrompt: [
13716
13908
  'You are the platform entity specialist for ACoreX.',
13717
13909
  'Use PlatformManagement:ListRegisteredEntities to discover or validate Module.Entity keys and to inspect entity definitions (required fields, types).',
13910
+ 'When explaining fields to end users in chat, mention **human-readable `title`** text from **`properties`**; use internal **`name`** only when the user wants technical/schema detail.',
13718
13911
  'Use ConnectivityMock:EntityStorage:Query to list or search stored rows once the entity key is known.',
13912
+ 'If the query is paginated or totals/charts need **every** row, **fetch remaining pages** (next offset/cursor per schema) in further tool turns until complete — do not ask the user to approve each page.',
13719
13913
  'Use Entity:Create and Entity:Update only with arguments that match each command schema; confirm outcomes from tool results and never fabricate success.',
13720
13914
  'Prefer read-only queries before mutations when you still need identifiers or schema details.',
13915
+ 'When the user wants a **chart** from stored rows, finish accurate aggregation first, then let the supervisor route **widget-chart-layout**; keep your own prose minimal.',
13721
13916
  ].join('\n'),
13722
13917
  modelEntityId: null,
13723
13918
  maxSteps: 10,
@@ -13725,7 +13920,7 @@ const AI_AGENT_MOCK = [
13725
13920
  {
13726
13921
  id: AXMAiAgentWidgetFormLayoutId,
13727
13922
  name: 'widget-form-layout',
13728
- title: M$17('Form & platform layout (AXPWidgetNode)', 'فرم و چیدمان پلتفرم (AXPWidgetNode)'),
13923
+ title: M$17('Form Layout Agent', 'دستیار چیدمان فرم'),
13729
13924
  description: M$17('Builds platform widget trees for forms and chat UI: **repeater-layout**, **select-editor** + **dataSource** (use **ListRegisteredDataSources**), **lookup-editor** + **ListRegisteredEntities**, **`text-editor`** last. Uses scoped **Widgets:GetForAI** (`agent: widget-form-layout`) and **ValidateLayoutJsonForAi**. Supervisor wraps as {"type":"node","content":...}.', 'درخت ویجت پلتفرم برای فرم و UI چت؛ repeater-layout، select-editor با dataSource، lookup-editor با ListRegisteredEntities، و در نهایت text-editor. از Widgets:GetForAI با scope فرم و ValidateLayoutJsonForAi استفاده می‌کند؛ سرپرست خروجی را در {"type":"node","content":...} می‌پیچد.'),
13730
13925
  toolIds: [
13731
13926
  aiAgentCommandBinding(axcResolveCommandRegistrySeedId(AXM_AI_REGISTRY_COMMAND_NAME.aiFormbuilderValidateLayoutJsonForAi)),
@@ -13889,8 +14084,8 @@ const AI_AGENT_MOCK = [
13889
14084
  {
13890
14085
  id: AXMAiAgentWidgetChartLayoutId,
13891
14086
  name: 'widget-chart-layout',
13892
- title: M$17('Dashboard chart tiles (AXPWidgetNode)', 'کاشی نمودار داشبورد (AXPWidgetNode)'),
13893
- description: M$17('Builds **dashboard chart** widget nodes (bar, line, donut, gauge, funnel, heatmap). Uses scoped **Widgets:GetForAI** (`agent: widget-chart-layout`), **ListRegisteredDataSources**, and **ValidateLayoutJsonForAi**. Supervisor wraps as {"type":"node","content":...}.', 'گره‌های ویجت **نمودار داشبورد** (میله، خط، دونات، گیج، قیف، heatmap). از Widgets:GetForAI با scope نمودار، ListRegisteredDataSources و ValidateLayoutJsonForAi استفاده می‌کند.'),
14087
+ title: M$17('Chart Generator Agent', 'دستیار تولید نمودار'),
14088
+ description: M$17('Builds **chart visualization** widget trees (bar, line, donut, gauge, funnel, heatmap) as renderable layout JSON for chat or embedded UI — independent chart specialist. Uses scoped **Widgets:GetForAI** (`agent: widget-chart-layout`), **ListRegisteredDataSources**, and **ValidateLayoutJsonForAi**. Supervisor wraps as {"type":"node","content":...}.', 'درخت ویجت **نمودار** (میله، خط، دونات، گیج، قیف، heatmap) به‌صورت JSON چیدمان قابل رندر برای چت؛ دستیار مستقل نمودار. از Widgets:GetForAI با scope نمودار، ListRegisteredDataSources و ValidateLayoutJsonForAi استفاده می‌کند.'),
13894
14089
  toolIds: [
13895
14090
  aiAgentCommandBinding(axcResolveCommandRegistrySeedId(AXM_AI_REGISTRY_COMMAND_NAME.aiFormbuilderValidateLayoutJsonForAi)),
13896
14091
  ],
@@ -13901,56 +14096,25 @@ const AI_AGENT_MOCK = [
13901
14096
  aiAgentQueryBinding(axcResolveQueryRegistrySeedId(AXM_AI_REGISTRY_QUERY_NAME.listRegisteredDataSources)),
13902
14097
  ],
13903
14098
  systemPrompt: [
13904
- 'You are the **dashboard chart tile** specialist for ACoreX. Your **only** successful outcome is a renderable **AXPWidgetNode** JSON for chart dashboard widgets no tutorials, no markdown fences, no prose in the final message.',
14099
+ 'You are the **chart visualization** specialist for ACoreX — an **independent chart generator**. Your **only** successful outcome is renderable **AXPWidgetNode** JSON for **data charts** (bar, line, donut, gauge, funnel, heatmap): no tutorials, no markdown fences, no prose in the final message.',
13905
14100
  '',
13906
14101
  '## Scope',
13907
- '- **Widgets:GetForAI** lists only **chart** dashboard catalog rows for this agent (tool defaults inject `agent: widget-chart-layout`). Registry `type` values look like `DashboardManagement:Widget:Dashboard:BarChart`, `LineChart`, `DonutChart`, `GaugeChart`, `FunnelChart`, `HeatmapChart`.',
14102
+ '- **Widgets:GetForAI** lists **chart-type** catalog definitions for this specialist (`agent: widget-chart-layout`). Pick the chart kind that matches the user goal.',
13908
14103
  '- Use **PlatformManagement:ListRegisteredDataSources** when you need registry keys or column metadata for `options.dataSource` / `dataSourceOptions` wiring.',
13909
14104
  '',
13910
14105
  '## Discovery',
13911
- '- Call **Widgets:GetForAI** with `name` set to the exact catalog registry name you will emit as **`AXPWidgetNode.type`**. Read **`detail.structured.inputs`** for paths such as `dataSourceOptions`, `path`, `name` — never invent nested option shapes.',
14106
+ '- Call **Widgets:GetForAI** with `name` set to the **exact** catalog registry name you will emit as **`AXPWidgetNode.type`** (copy from tool rows — full string, never an invented alias). Read **`detail.structured.inputs`** for paths such as `dataSourceOptions`, `path`, `name` — never invent nested option shapes.',
13912
14107
  '',
13913
14108
  '## Output contract',
13914
14109
  '- Output the **inner** widget root only (no `{ "type":"node", "content": ... }` envelope).',
13915
- '- **AXPWidgetNode.type** must be the **full** dashboard widget registry name from the catalog, not a short alias.',
14110
+ '- **AXPWidgetNode.type** must equal the catalog registry name returned by **Widgets:GetForAI** for your chosen chart widget.',
13916
14111
  '- **Do not** use **`document-layout`** as the root unless the supervisor context explicitly requires a Form Template designer export.',
13917
14112
  '',
13918
14113
  '## Validation',
13919
14114
  '- You **must** call **AiFormbuilder:ValidateLayoutJsonForAi** on the draft tree. When **`data.valid`** is true, your **final** message is **exactly** **`data.normalizedJson`** (one parseable JSON object, no markdown fences, no extra prose).',
13920
- ].join('\n'),
13921
- modelEntityId: null,
13922
- maxSteps: 16,
13923
- },
13924
- {
13925
- id: AXMAiAgentWidgetDashboardLayoutId,
13926
- name: 'widget-dashboard-layout',
13927
- title: M$17('Dashboard tiles — KPI & utility (AXPWidgetNode)', 'کاشی داشبورد — KPI و ابزار (AXPWidgetNode)'),
13928
- description: M$17('Builds **non-chart** dashboard tiles: KPI cards, weather, clocks, shortcuts, sticky notes, etc. Uses scoped **Widgets:GetForAI** (`agent: widget-dashboard-layout`), **ListRegisteredDataSources**, and **ValidateLayoutJsonForAi**. Supervisor wraps as {"type":"node","content":...}.', 'کاشی‌های **غیرنموداری** داشبورد: KPI، آب‌وهوا، ساعت، shortcut، یادداشت و غیره. از Widgets:GetForAI با scope داشبورد، ListRegisteredDataSources و ValidateLayoutJsonForAi استفاده می‌کند.'),
13929
- toolIds: [
13930
- aiAgentCommandBinding(axcResolveCommandRegistrySeedId(AXM_AI_REGISTRY_COMMAND_NAME.aiFormbuilderValidateLayoutJsonForAi)),
13931
- ],
13932
- queryIds: [
13933
- aiAgentQueryBinding(axcResolveQueryRegistrySeedId(AXM_AI_REGISTRY_QUERY_NAME.widgetsGetForAi), {
13934
- agent: 'widget-dashboard-layout',
13935
- }),
13936
- aiAgentQueryBinding(axcResolveQueryRegistrySeedId(AXM_AI_REGISTRY_QUERY_NAME.listRegisteredDataSources)),
13937
- ],
13938
- systemPrompt: [
13939
- 'You are the **dashboard tile** specialist for ACoreX (KPI, utility, weather, clocks, shortcuts, sticky notes, and other **non-chart** `DashboardManagement:Widget:Dashboard:*` widgets). Your **only** successful outcome is renderable **AXPWidgetNode** JSON.',
13940
- '',
13941
- '## Scope',
13942
- '- **Widgets:GetForAI** lists only **non-chart** dashboard catalog rows for this agent (defaults inject `agent: widget-dashboard-layout`).',
13943
- '- Use **PlatformManagement:ListRegisteredDataSources** when tiles need bound tabular or list data.',
13944
- '',
13945
- '## Discovery',
13946
- '- Call **Widgets:GetForAI** with the target widget **`name`** before wiring **`options`**. Follow **`detail.structured.inputs`** for `dataSourceOptions`, titles, paths, and display hints.',
13947
- '',
13948
- '## Output contract',
13949
- '- Inner tree only (no supervisor chat envelope). **AXPWidgetNode.type** must match the catalog registry name exactly.',
13950
- '- Do not put forbidden DOM/CSS keys on nodes; use documented **options** only.',
13951
14115
  '',
13952
- '## Validation',
13953
- '- You **must** call **AiFormbuilder:ValidateLayoutJsonForAi**; when **`data.valid`** is true, your **final** reply is **exactly** **`data.normalizedJson`**.',
14116
+ '## Data behind charts',
14117
+ '- If counts or series still depend on missing pages of source data, finish entity queries (pagination) **before** emitting chart JSON — do not apologize at length for partial data.',
13954
14118
  ].join('\n'),
13955
14119
  modelEntityId: null,
13956
14120
  maxSteps: 16,
@@ -13958,7 +14122,7 @@ const AI_AGENT_MOCK = [
13958
14122
  {
13959
14123
  id: AXMAiAgentCommonToolsId,
13960
14124
  name: 'current-time',
13961
- title: M$17('Current time', 'زمان فعلی'),
14125
+ title: M$17('Current Time', 'زمان فعلی'),
13962
14126
  description: M$17('ONLY when the user explicitly asks for the current date/time, clock, timezone, or locale-specific time. Do NOT use for greetings, small talk, connectivity tests, or unrelated tasks. Registry tool: common.get_current_time.', 'فقط وقتی کاربر صریحاً تاریخ/زمان فعلی، ساعت، منطقهٔ زمانی یا زمان محلی را می‌خواهد. برای احوال‌پرسی، تست اتصال یا کارهای نامرتبط استفاده نکنید. ابزار رجیستری: common.get_current_time.'),
13963
14127
  toolIds: [aiAgentCommandBinding(axcResolveCommandRegistrySeedId(AXM_AI_REGISTRY_COMMAND_NAME.commonGetCurrentTime))],
13964
14128
  queryIds: [],
@@ -13973,11 +14137,11 @@ const AI_AGENT_MOCK = [
13973
14137
  {
13974
14138
  id: AXMAiAgentImageGenerationId,
13975
14139
  name: 'image-generation',
13976
- title: M$17('Image generation', 'تولید تصویر'),
14140
+ title: M$17('Image Generation Agent', 'دستیار تولید تصویر'),
13977
14141
  description: M$17('In-chat image generation when AiManagement:ChatGenerateImage is registered in the command catalog. If no image tool is available, explain that image generation is not configured.', 'تولید تصویر در چت وقتی AiManagement:ChatGenerateImage در کاتالوگ فرمان ثبت شده باشد. اگر ابزار تصویر موجود نیست، توضیح دهید که تولید تصویر پیکربندی نشده است.'),
13978
14142
  toolIds: [
13979
14143
  aiAgentCommandBinding(axcResolveCommandRegistrySeedId(AXM_AI_REGISTRY_COMMAND_NAME.imageGeneration), {
13980
- 'modelId': 'a0000001-0000-4000-8000-000000000031'
14144
+ // 'modelId': 'a0000001-0000-4000-8000-000000000031'
13981
14145
  }),
13982
14146
  ],
13983
14147
  queryIds: [],
@@ -13993,7 +14157,7 @@ const AI_AGENT_MOCK = [
13993
14157
  {
13994
14158
  id: AXMAiAgentSpeechToTextId,
13995
14159
  name: 'speech-to-text',
13996
- title: M$17('Speech to text', 'گفتار به متن'),
14160
+ title: M$17('Speech-to-Text Agent', 'دستیار گفتار به متن'),
13997
14161
  description: M$17('Transcribes user-attached audio when AiManagement:ChatTranscribeSpeech is registered. Default speech catalog model is set on this assist\u2019s delegated row (options.model).', 'رونویسی صوت پیوست‌شدهٔ کاربر وقتی AiManagement:ChatTranscribeSpeech ثبت شده باشد. مدل پیش‌فرض گفتار روی ردیف delegated این assist (options.model) تنظیم می‌شود.'),
13998
14162
  toolIds: [aiAgentCommandBinding(axcResolveCommandRegistrySeedId(AXM_AI_REGISTRY_COMMAND_NAME.chatTranscribeSpeech))],
13999
14163
  queryIds: [],
@@ -14010,7 +14174,7 @@ const AI_AGENT_MOCK = [
14010
14174
  {
14011
14175
  id: AXMAiAgentTextToSpeechId,
14012
14176
  name: 'text-to-speech',
14013
- title: M$17('Text to speech', 'متن به گفتار'),
14177
+ title: M$17('Text-to-Speech Agent', 'دستیار متن به گفتار'),
14014
14178
  description: M$17('Spoken audio from text when AiManagement:ChatSynthesizeSpeech is registered. Defaults for model and voice come from this assist\u2019s delegated specialist row (options.model / options.voice).', 'خروجی صوتی از متن وقتی AiManagement:ChatSynthesizeSpeech ثبت شده باشد. پیش‌فرض مدل و صدا از ردیف specialist delegated این assist (options.model / options.voice) می‌آید.'),
14015
14179
  toolIds: [aiAgentCommandBinding(axcResolveCommandRegistrySeedId(AXM_AI_REGISTRY_COMMAND_NAME.chatSynthesizeSpeech))],
14016
14180
  queryIds: [],
@@ -14027,7 +14191,7 @@ const AI_AGENT_MOCK = [
14027
14191
  {
14028
14192
  id: AXMAiAgentDocumentOcrId,
14029
14193
  name: 'document-ocr',
14030
- title: M$17('Document OCR', 'OCR سند'),
14194
+ title: M$17('Document Understanding Agent', 'دستیار درک اسناد'),
14031
14195
  description: M$17('Transcribes text from document or photo images (scans, forms, handwriting, medical paperwork). Uses AiManagement:ExtractDocumentText with a stored image fileId. Not a substitute for professional medical interpretation.', 'متن را از تصاویر سند یا عکس (اسکن، فرم، دست‌خط، پروندهٔ پزشکی) استخراج می‌کند؛ با AiManagement:ExtractDocumentText و fileId ذخیره‌شده. جایگزین تفسیر پزشکی حرفه‌ای نیست.'),
14032
14196
  toolIds: [aiAgentCommandBinding(axcResolveCommandRegistrySeedId(AXM_AI_REGISTRY_COMMAND_NAME.extractDocumentText))],
14033
14197
  queryIds: [],
@@ -14044,10 +14208,15 @@ const AI_AGENT_MOCK = [
14044
14208
  {
14045
14209
  id: AXMAiAgentCentralizedPaymentGuideId,
14046
14210
  name: '2a0e1e4d-ddfe-4f04-b7ba-2fd307eb5967',
14047
- title: M$17('Centralized payment guide', 'راهنمای سامانه پرداخت متمرکز'),
14048
- description: M$17('Guide assistant for the centralized payment system in commerce; answers user questions about payment procedures and concepts without platform command or query tools.', 'دستیار راهنما برای سامانه پرداخت متمرکز در حوزه تجارت؛ پاسخ‌گوی سوالات کاربر دربارهٔ رویه‌ها و مفاهیم پرداخت بدون ابزار فرمان یا پرس‌وجوی داخلی پلتفرم.'),
14211
+ title: M$17('Centralized Payment Guide Agent', 'دستیار راهنمای پرداخت متمرکز'),
14212
+ description: M$17('Priority guide for the centralized commerce payment system. Assist should prefer delegating here whenever the topic is e-wallet or centralized payments (no platform command or query tools). Typical questions: paying via e-wallet, withdrawing from the wallet, charging or topping up the wallet, reporting and transaction history.', 'راهنمای اولویت‌دار سامانه پرداخت متمرکز تجارت؛ assist برای موضوعات کیف پول الکترونیک و پرداخت متمرکز باید تا حد ممکن این agent را فراخوانی کند (بدون ابزار فرمان یا پرس‌وجوی داخلی پلتفرم). نمونهٔ سوالات: نحوهٔ پرداخت از طریق کیف پول الکترونیک، برداشت از کیف پول، شارژ کیف پول، گزارش‌گیری و تاریخچهٔ تراکنش‌ها.'),
14049
14213
  toolIds: [],
14050
14214
  queryIds: [],
14215
+ systemPrompt: [
14216
+ 'Always end your reply with a one-line source disclaimer addressed to the user:',
14217
+ '- If the user wrote primarily in Persian or your answer is in Persian, end with exactly: این اطلاعات بر اساس مستندات سازمان تجارت است.',
14218
+ '- If the user wrote primarily in English or your answer is in English, end with: This information is based on the official documentation of the Organization of Commerce.',
14219
+ ].join('\n'),
14051
14220
  modelEntityId: AXMAiModelStableIds.demisAi,
14052
14221
  maxSteps: 8,
14053
14222
  },
@@ -14068,15 +14237,26 @@ function aiModelRef(catalogId) {
14068
14237
  }
14069
14238
  //#endregion
14070
14239
  //#region ---- Stable assist id ----
14071
- /** Deterministic id for the platform default assist row. */
14072
- const AXMAiPlatformDefaultAssistId = 'b0000001-0000-4000-8000-000000000001';
14073
- /** Deterministic id for the Demis AI default assist row (mirror of platform default, Demis model). */
14074
- const AXMAiDemisDefaultAssistId = 'b0000001-0000-4000-8000-000000000004';
14240
+ /** Deterministic id for the platform assistant assist row. */
14241
+ const AXMAiPlatformAssistantAssistId = 'b0000001-0000-4000-8000-000000000001';
14242
+ /** Deterministic id for the Demis AI assistant assist row (mirror of platform assistant, lighter delegation). */
14243
+ const AXMAiDemisAssistantAssistId = 'b0000001-0000-4000-8000-000000000004';
14075
14244
  //#endregion
14076
14245
  //#region ---- Seed text: supervisor assists ----
14077
14246
  /** Supervisor assist: tools are delegated specialists (`agent:<AiAgent catalog id>`), not raw registry tools. */
14078
14247
  const SEED_SUPERVISOR_AGENTS_HINT = [
14079
14248
  'You are the primary assistant. Your tools are delegated specialists; each function name is `agent:` plus the AiAgent row id from the tool list.',
14249
+ '',
14250
+ '## ACoreX scope and grounding (mandatory)',
14251
+ '- **Scope:** Treat every user question as being about **this ACoreX platform deployment** — navigation, modules, entities, stored data, and behaviors your tools expose. Do not substitute generic product patterns or other apps unless the user clearly wants **general** knowledge **and** no delegated tool applies.',
14252
+ '- **No guessing:** Never invent or assume **menu paths** or breadcrumbs, **record counts**, specific **stored rows**, **field or property names**, **entity/module keys**, **status** values, or other catalog or data facts.',
14253
+ '- **Agent-first:** For any **platform-specific** question (where to go in the UI, how to complete a task in the app, what the menu/catalog contains, what is stored, schemas, widgets), **invoke the best-matching delegated `agent:` tool in this turn before you answer in prose** — not from model memory alone. If routing is unclear, start with **platform-help** (navigation and catalog guidance), then chain **platform-entity** or others when the user needs stored data or mutations.',
14254
+ '- **Prefer tools:** Use specialists whenever they can return authoritative results; avoid long speculative reasoning instead of calling a tool.',
14255
+ '',
14256
+ '## Reply style',
14257
+ '- **Short and direct.** Deliver the outcome first (facts, chart/table layout envelope, or routed specialist result). Avoid long explanations, hedging, or asking permission for obvious follow-up tool calls.',
14258
+ '- Chain agents silently when needed (e.g. fetch **all** pages for totals, then **widget-chart-layout** for a chart).',
14259
+ '',
14080
14260
  '- Route each user request to the best-matching agent tool. You may call more than one agent when the request spans domains.',
14081
14261
  '- Pass a clear `query` string (or structured args if the tool schema allows) so the specialist can act without guessing.',
14082
14262
  '- Ground factual answers in agent tool results; do not invent platform data.',
@@ -14084,40 +14264,60 @@ const SEED_SUPERVISOR_AGENTS_HINT = [
14084
14264
  '- For reading text from an attached image, scan, or document photo, route to the document OCR specialist so it can call the extraction tool with the correct fileId.',
14085
14265
  '- For transcribing attached audio or voice notes to text, route to the speech-to-text specialist.',
14086
14266
  '- For spoken audio, read-aloud, or text-to-speech from user text, route to the text-to-speech specialist.',
14087
- '- For structured layout or widget tree JSON (AXPWidgetNode) the UI can render, route to the correct **widget specialist**: **widget-form-layout** (platform forms, chat tables, editors), **widget-chart-layout** (dashboard chart tiles only), or **widget-dashboard-layout** (KPI, weather, clocks, shortcuts, sticky notes, and other non-chart dashboard tiles).',
14267
+ '- For structured layout or widget tree JSON (AXPWidgetNode) the UI can render, route to the correct **widget specialist**: **widget-form-layout** (platform forms, chat tables, editors) or **widget-chart-layout** (standalone chart generator bar, line, donut, gauge, funnel, heatmap).',
14088
14268
  '- When the user asks to **show**, **list**, **compare**, or **report** on **several similar records** (products, orders, rows, search hits), do not rely on long plain-text bullet lists alone: after you have **real rows** from a data specialist (e.g. platform-entity), call **widget-form-layout** and pass those facts so it builds a **`table-layout`** tree (it discovers shapes via scoped **Widgets:GetForAI**).',
14089
14269
  '- When the user needs a **form-like** chat UI (questions, labeled inputs, mini survey, or data-entry outline), call **widget-form-layout** so it composes **`form-field`** nodes with registry editors discovered via scoped **Widgets:GetForAI**.',
14090
- '- For **dashboard bar/line/donut/gauge/funnel/heatmap** tiles or chart-centric JSON, call **widget-chart-layout**.',
14091
- '- For **dashboard KPI cards, weather, clocks, shortcuts, sticky notes**, call **widget-dashboard-layout**.',
14092
- '- **Chaining specialists is expected**: e.g. call platform-entity (or another data agent) first, then a widget specialist for presentation; your final user-visible layout reply uses the node envelope below when the last step is output from **widget-form-layout**, **widget-chart-layout**, or **widget-dashboard-layout**.',
14270
+ '- For **charts** or chart-centric visualization JSON (bar, line, donut, gauge, funnel, heatmap), call **widget-chart-layout**.',
14271
+ '- **Chaining specialists is expected**: e.g. call platform-entity (or another data agent) first, then a widget specialist for presentation; your final user-visible layout reply uses the node envelope below when the last step is output from **widget-form-layout** or **widget-chart-layout**.',
14272
+ '- For **optional follow-up chip buttons** in Conversation assist, delegate to **widget-follow-up-chips-layout** (scoped **Widgets:GetForAI** `flex-layout` + `button-action` only, same pattern as **widget-chart-layout**). Keep your main answer as plain prose, then append `{ "type":"node","content": <inner root from specialist> }` using the specialist’s validated JSON (no markdown fences).',
14273
+ '- For **how-to**, **where in the app**, **which menu**, or introductory platform tasks, delegate to **platform-help**. Summarize in **plain language** using **`title`** breadcrumbs from tool results; omit internal JSON keys unless the user asks for technical detail. Prefer **facts from that specialist’s tool JSON** — do not invent guessed menu paths when navigation search failed.',
14274
+ '- **platform-help** is navigation + entity-catalog guidance (**read-only** queries). Chain **platform-entity** afterward when users need persisted data inspection, schemas for mutations, or create/update tooling.',
14093
14275
  '',
14094
14276
  '## Widget / layout UI (delegated widget specialists)',
14095
- '- When a widget specialist returns JSON for the UI, your **final assistant reply MUST be exactly one JSON object** with this shape (no markdown fences, no extra prose):',
14277
+ '- When you need renderable layout from a specialist, your **final assistant reply** may interleave **plain prose** with one or more JSON objects shaped exactly as (no markdown fences):',
14096
14278
  ' `{"type":"node","content": <AXPWidgetNode>}`',
14097
- '- `<AXPWidgetNode>` is the widget tree from the specialist (`data.answer` in the agent tool result). If `data.answer` is already a string, parse it once; if it is a bare widget root object (e.g. starts with `"type":"block-layout"` or another registry root), use that object as `content`.',
14098
- '- Never paste only the inner widget JSON as plain chat text without the `{"type":"node","content":...}` wrapper — the chat surface classifies that envelope as a separate layout message type.',
14279
+ '- `<AXPWidgetNode>` is the inner widget root from the delegated specialist (a `node` entry in `data.responses` when the specialist returns layout JSON). Use **widget-follow-up-chips-layout** for chip rows (`flex-layout` + `button-action`).',
14280
+ '- Never paste bare inner widget JSON without the `{"type":"node","content":...}` wrapper — each wrapper becomes a separate interactive layout segment.',
14281
+ ].join('\n');
14282
+ /** Demis default assist only: single delegated agent (centralized payment guide)—no other specialist tools are available. */
14283
+ const SEED_DEMIS_CENTRALIZED_PAYMENT_GUIDE_ROUTING = [
14284
+ 'Your available tools are delegated specialists; each function name is `agent:` plus the AiAgent catalog id from the tool list.',
14285
+ '',
14286
+ '## Centralized payment guide (priority delegation)',
14287
+ '- When the user asks about the **centralized commerce payment system**, **e-wallet**, or **wallet workflows**, **prefer** the **centralized payment guide** delegated agent **first** (pick the matching `agent:` tool from your list) instead of improvising steps from general knowledge.',
14288
+ '- Treat these as mandatory delegation signals: paying via the e-wallet, withdrawing from the wallet, charging or topping up the wallet, **transaction history**, and **payment reporting**.',
14289
+ '',
14290
+ '## Verbatim relay after the centralized payment guide replies',
14291
+ '- When that delegated `agent:` tool **succeeds** with user-visible text in a `text` segment inside `data.responses`, your **final assistant message must mirror that text exactly** when policy requires a verbatim relay: same wording, punctuation, line breaks, lists, and the specialist closing disclaimer line. **Do not** shorten, lengthen, paraphrase, translate, summarize, bullet-wrap differently, or add prefixes/suffixes ("Here is what the guide said:", "In short", follow-up questions) unless those words already appear inside the specialist text.',
14292
+ '- **Do not** wrap the relay in markdown fences or extra headings unless the specialist output already contains them.',
14099
14293
  ].join('\n');
14100
14294
  //#endregion
14101
14295
  //#region ---- Default Assists ----
14102
14296
  const AI_ASSIST_MOCK = [
14103
14297
  {
14104
- id: AXMAiPlatformDefaultAssistId,
14105
- name: 'platform-default',
14106
- title: M$16('Platform Default', 'پیش‌فرض پلتفرم'),
14298
+ id: AXMAiPlatformAssistantAssistId,
14299
+ name: 'platform-assistant',
14300
+ title: M$16('Platform Assistant', 'دستیار پلتفرم'),
14107
14301
  description: M$16('Default platform assistant used when no specific assist is selected.', 'دستیار پیش‌فرض پلتفرم وقتی هیچ assist مشخصی انتخاب نشده باشد.'),
14108
14302
  modelId: AXMAiModelStableIds.gpt54,
14109
14303
  aiModel: aiModelRef(AXMAiModelStableIds.gpt54),
14110
14304
  tools: [],
14111
14305
  systemPrompt: [
14112
- 'You are a helpful assistant for the ACoreX platform. Be concise, accurate, and safe. If you lack context, say so.',
14306
+ 'You are a helpful assistant for the ACoreX platform. Be **brief**, accurate, and safe. Skip jargon unless the user asks for technical detail.',
14307
+ 'Answer in **this product’s** scope only; for menus, catalog, or stored data, call the matching delegated agent **before** answering — do not guess.',
14113
14308
  '',
14114
14309
  SEED_SUPERVISOR_AGENTS_HINT,
14115
14310
  ].join('\n'),
14116
14311
  initialMessages: '',
14117
14312
  professionImageUrl: '',
14118
- imageModelId: AXMAiModelStableIds.imagen4Generate001,
14313
+ imageModelId: AXMAiModelStableIds.openaiGptImage1,
14119
14314
  planningMode: 'once',
14120
14315
  delegatedAgents: [
14316
+ {
14317
+ agent: {
14318
+ type: AXMAiAgentPlatformHelpId,
14319
+ },
14320
+ },
14121
14321
  {
14122
14322
  agent: {
14123
14323
  type: AXMAiAgentPlatformEntityId,
@@ -14131,7 +14331,7 @@ const AI_ASSIST_MOCK = [
14131
14331
  {
14132
14332
  agent: {
14133
14333
  type: AXMAiAgentImageGenerationId,
14134
- options: { model: AXMAiModelStableIds.imagen4Generate001 },
14334
+ options: { model: AXMAiModelStableIds.openaiGptImage1 },
14135
14335
  },
14136
14336
  },
14137
14337
  {
@@ -14163,34 +14363,31 @@ const AI_ASSIST_MOCK = [
14163
14363
  },
14164
14364
  {
14165
14365
  agent: {
14166
- type: AXMAiAgentWidgetDashboardLayoutId,
14366
+ type: AXMAiAgentWidgetFollowUpChipsLayoutId,
14167
14367
  },
14168
14368
  },
14169
14369
  ],
14170
14370
  },
14171
14371
  {
14172
- id: AXMAiDemisDefaultAssistId,
14173
- name: 'demis-default',
14174
- title: M$16('Demis Default', 'پیش‌فرض دیمیس'),
14372
+ id: AXMAiDemisAssistantAssistId,
14373
+ name: 'demis-assistant',
14374
+ title: M$16('Demis Assistant', 'دستیار دیمیس'),
14175
14375
  description: M$16('Default platform assistant used when no specific assist is selected.', 'دستیار پیش‌فرض پلتفرم وقتی هیچ assist مشخصی انتخاب نشده باشد.'),
14176
14376
  modelId: AXMAiModelStableIds.gpt54,
14177
14377
  aiModel: aiModelRef(AXMAiModelStableIds.gpt54),
14178
14378
  tools: [],
14179
14379
  systemPrompt: [
14180
- 'You are a helpful assistant for the ACoreX platform. Be concise, accurate, and safe. If you lack context, say so.',
14380
+ 'You are a helpful assistant for the ACoreX platform. Be **brief**, accurate, and safe. Skip jargon unless the user asks for technical detail.',
14381
+ 'Answer in **this product’s** scope only; for menus, catalog, or stored data, call the matching delegated agent **before** answering — do not guess.',
14181
14382
  '',
14182
- SEED_SUPERVISOR_AGENTS_HINT,
14383
+ SEED_DEMIS_CENTRALIZED_PAYMENT_GUIDE_ROUTING,
14183
14384
  ].join('\n'),
14184
14385
  initialMessages: '',
14185
14386
  professionImageUrl: '',
14186
- imageModelId: AXMAiModelStableIds.imagen4Generate001,
14187
- planningMode: 'once',
14188
- delegatedAgents: [
14189
- { agent: { type: AXMAiAgentPlatformEntityId } },
14190
- { agent: { type: AXMAiAgentWidgetFormLayoutId } },
14191
- { agent: { type: AXMAiAgentWidgetChartLayoutId } },
14192
- { agent: { type: AXMAiAgentWidgetDashboardLayoutId } },
14193
- ],
14387
+ imageModelId: AXMAiModelStableIds.openaiGptImage1,
14388
+ // No planning preamble: this assist only delegates to the payment guide; a tool-free planning turn would surface as "thinking" with little benefit.
14389
+ planningMode: 'off',
14390
+ delegatedAgents: [{ agent: { type: AXMAiAgentCentralizedPaymentGuideId } }],
14194
14391
  },
14195
14392
  {
14196
14393
  id: 'b0000001-0000-4000-8000-000000000002',
@@ -14210,23 +14407,34 @@ const AI_ASSIST_MOCK = [
14210
14407
  id: 'b0000001-0000-4000-8000-000000000003',
14211
14408
  name: 'general-assistant',
14212
14409
  title: M$16('General Assistant', 'دستیار عمومی'),
14213
- description: M$16('A general-purpose assistant that routes to platform entity, utility, and image specialists (delegated agent tools).', 'دستیار چندمنظوره که به specialistهای موجودیت پلتفرم، ابزار و تصویر (ابزارهای عامل واگذارشده) هدایت می‌کند.'),
14410
+ description: M$16('A general-purpose assistant that routes to platform help/navigation, platform entity tooling, utilities, media, image, and delegated layout specialists.', 'دستیار چندمنظوره که به دستیار راهنمای پلتفرم، موجودیت پلتفرم، ابزارها، رسانه‌ها، تصویر و چیدمان (delegated specialists) متصل می‌شود.'),
14214
14411
  modelId: AXMAiModelStableIds.gemini25Flash,
14215
14412
  aiModel: aiModelRef(AXMAiModelStableIds.gemini25Flash),
14216
14413
  tools: [],
14217
14414
  systemPrompt: [
14218
- 'You are a helpful, friendly assistant. Be concise and clear.',
14415
+ 'You are a helpful, friendly assistant. Be **brief**; use everyday language unless the user wants technical identifiers.',
14416
+ 'When the user means **this ACoreX app** (menus, features, stored data), call the matching delegated agent **before** answering — do not guess paths or records.',
14219
14417
  '',
14220
14418
  SEED_SUPERVISOR_AGENTS_HINT,
14221
14419
  ].join('\n'),
14222
14420
  initialMessages: 'Hi! How can I help you today?',
14223
14421
  professionImageUrl: '',
14224
- imageModelId: AXMAiModelStableIds.imagen4Generate001,
14422
+ imageModelId: AXMAiModelStableIds.openaiGptImage1,
14225
14423
  delegatedAgents: [
14424
+ {
14425
+ agent: {
14426
+ type: AXMAiAgentPlatformHelpId,
14427
+ },
14428
+ },
14429
+ {
14430
+ agent: {
14431
+ type: AXMAiAgentPlatformEntityId,
14432
+ },
14433
+ },
14226
14434
  {
14227
14435
  agent: {
14228
14436
  type: AXMAiAgentImageGenerationId,
14229
- options: { model: AXMAiModelStableIds.imagen4Generate001 },
14437
+ options: { model: AXMAiModelStableIds.openaiGptImage1 },
14230
14438
  },
14231
14439
  },
14232
14440
  {
@@ -14253,7 +14461,7 @@ const AI_ASSIST_MOCK = [
14253
14461
  },
14254
14462
  {
14255
14463
  agent: {
14256
- type: AXMAiAgentWidgetDashboardLayoutId,
14464
+ type: AXMAiAgentWidgetFollowUpChipsLayoutId,
14257
14465
  },
14258
14466
  },
14259
14467
  ],
@@ -14706,8 +14914,7 @@ function axpAiLastUserTranscriptText(messages) {
14706
14914
  function axpAiBuildPlanningAddendum(toolSchemas, includeRichToolHints) {
14707
14915
  const lines = [
14708
14916
  '## Planning turn (no tools)',
14709
- 'Reply only with a short plan: 2–5 bullet points of what you will do next.',
14710
- 'Do not call tools in this turn. The next turn will allow tools.',
14917
+ 'Reply with **at most 3** short bullets next actions only. No tools this turn.',
14711
14918
  ];
14712
14919
  if (includeRichToolHints && toolSchemas.length > 0) {
14713
14920
  lines.push('', 'Available tools (names only; full schemas follow in the next turn):');
@@ -14729,8 +14936,7 @@ function planningToolBulletLine(s) {
14729
14936
  function axpAiBuildPlanningAddendumGrouped(commandToolSchemas, queryToolSchemas, includeRichToolHints) {
14730
14937
  const lines = [
14731
14938
  '## Planning turn (no tools)',
14732
- 'Reply only with a short plan: 2–5 bullet points of what you will do next.',
14733
- 'Do not call tools in this turn. The next turn will allow tools.',
14939
+ 'Reply with **at most 3** short bullets next actions only. No tools this turn.',
14734
14940
  ];
14735
14941
  if (!includeRichToolHints) {
14736
14942
  return lines.join('\n');
@@ -14764,8 +14970,7 @@ function axpAiBuildPlanningAddendumGrouped(commandToolSchemas, queryToolSchemas,
14764
14970
  function axpAiBuildDelegatedSingleToolPolicyAddendum() {
14765
14971
  return [
14766
14972
  '## Tool usage (delegated specialist)',
14767
- 'When you need registry tools, request **at most one** tool call per assistant turn.',
14768
- 'After each tool result, you will get a short reflection turn to interpret the outcome before choosing the next tool.',
14973
+ 'At most **one** registry tool call per assistant turn; a brief no-tool reflection follows each result.',
14769
14974
  ].join('\n');
14770
14975
  }
14771
14976
  /**
@@ -14775,11 +14980,7 @@ function axpAiBuildDelegatedSingleToolPolicyAddendum() {
14775
14980
  function axpAiBuildDelegatedToolReflectionAddendum() {
14776
14981
  return [
14777
14982
  '## Reflection turn (no tools)',
14778
- 'You just received a tool result. Start with **one sentence (Think)** summarizing what changed in your understanding, then **Plan** with 2–4 short bullet points:',
14779
- '- What the output means (`success`, `error`, and payload fields such as `data.valid` / `data.errors` when present).',
14780
- '- If labels or entity names differ from the user’s wording (e.g. synonyms, registry keys), map them explicitly.',
14781
- '- Whether you need another tool or can answer; if another tool, which one and why.',
14782
- 'Do not call tools in this turn. The next turn will allow tools again.',
14983
+ '**One sentence**: what the tool returned (`success` / `error`, key `data` fields). **Then 1–2 bullets**: next single tool (if any) or finish. No tools this turn.',
14783
14984
  ].join('\n');
14784
14985
  }
14785
14986
  //#endregion
@@ -15329,50 +15530,36 @@ function parseChatTransport(raw) {
15329
15530
  //#region ---- System prompt augmentation ----
15330
15531
  /**
15331
15532
  * Appended to assist system prompt when at least one tool is exposed.
15332
- * Written for LLM consumption: imperative rules, no ambiguity about evidence vs. speculation.
15533
+ * Balanced for grounded tool use, concise user-visible replies, and autonomous completion (e.g. pagination).
15333
15534
  */
15334
15535
  const AI_CHAT_SYSTEM_TOOLS_BEHAVIOR_HINT = [
15335
- '## Tool result shape (every tool message)',
15336
- '- Normalized tool outputs use JSON with: `success` (boolean), optional `toolKind` (`command` for mutations via command registry, `query` for read-only fetches), `data` (payload when `success` is true), and `error` (short string when `success` is false).',
15337
- '- Branch on `success` before trusting `data`. Use `toolKind` to reason about side effects: `query` should not mutate platform state; `command` may.',
15338
- '- On failure, read `error`, adjust arguments or call a discovery/read tool, then retry. Do not assume success without `success: true`.',
15339
- '',
15340
- '## Tool-only execution policy',
15341
- '- Assume zero knowledge about runtime state unless it comes from tools in this conversation or explicit user input.',
15342
- '- If the answer depends on platform data, you MUST call tool(s) first. Do not answer from memory or plausibility.',
15343
- '- Never guess IDs, keys, enum values, parameter shapes, counts, statuses, or outcomes.',
15344
- '- If no tool can provide required evidence, state what is missing and ask the user in chat. Do not fill gaps.',
15345
- '- For mutating actions, do read/list/get first to resolve exact targets, then execute mutation.',
15346
- '- If a tool errors, inspect the error, correct arguments using schema/discovery tools, and retry. Never fabricate success.',
15347
- '',
15348
- '## Tool argument discovery',
15349
- '- Read each tool schema before calling (required fields, types, allowed values). Schema is the contract.',
15350
- '- When an argument is unknown (entity/id/category/etc.), call discovery tools (list/search/get) to resolve valid values.',
15351
- '- Chain calls deterministically: list/search -> select value from result -> detail/action with that value.',
15352
- '- If ambiguity remains, ask the user in plain chat for one decision. Never invent a "likely" value.',
15536
+ '## Tools',
15537
+ '- Outputs are JSON: `success`, optional `toolKind` (`query` = read-only, `command` = may mutate), `data`, `error`. Use `data` only when `success` is true.',
15538
+ '- Platform facts require tools in this thread not memory or guesses. Never invent IDs, keys, counts, or statuses.',
15539
+ '- On `success: false`, read `error`, fix arguments or run a discovery/read tool, then retry.',
15540
+ '- **Pagination / completeness**: if totals, charts, or comparisons need **all** rows and the query supports paging/cursors, **call again** until done. Do **not** ask the user to approve an obvious next fetch.',
15541
+ '- Mutations: resolve targets with read/list tools first; infer outcomes only from tool results.',
15353
15542
  '',
15354
- '## Response constraints',
15355
- '- Every factual statement must be traceable to tool output in this thread or explicit user text.',
15356
- '- Do not claim completion, success, or side effects unless confirmed by tool output.',
15357
- '- If evidence is insufficient, return a blocked/incomplete response with the exact missing input or next tool call.',
15543
+ '## Answers',
15544
+ '- **Default: short.** Lead with the deliverable (facts, layout/chart envelope, or image). Avoid long disclaimers, repetition, and “if you want I can…”.',
15545
+ '- Ground every factual claim in tool output or explicit user text.',
15546
+ '- Ask **one** focused question only when something is **truly** ambiguous or **no** tool can supply evidence.',
15358
15547
  '',
15359
- '## Hard guardrails',
15360
- '- Never output speculative examples as if they are real platform data.',
15361
- '- Never continue with placeholders like "some-id", "example-key", or guessed defaults for required fields.',
15548
+ '## Guardrails',
15549
+ '- Do not present hypothetical examples as real data. Do not use placeholder IDs for required fields.',
15362
15550
  '',
15363
15551
  '## Image generation',
15364
15552
  `- When the user asks for a picture, illustration, drawing, diagram-as-image, or any raster-style visual, you MUST call "${AIMANAGEMENT_CHAT_GENERATE_IMAGE_COMMAND_KEY}" with a detailed "prompt" (subject, style, mood, composition).`,
15365
- '- Do not invent or paste fake image URLs in plain chat when this tool can produce the image.',
15366
- '- After the tool returns, you may briefly describe what was generated; the UI shows the image from tool output.',
15553
+ '- Do not invent fake image URLs when this tool can run.',
15554
+ '- After success, at most one short line; the UI renders the image from tool output.',
15367
15555
  '',
15368
15556
  '## Speech transcription',
15369
- `- When the user asks to transcribe, dictate, or convert attached audio or voice to text, you MUST call "${AIMANAGEMENT_CHAT_TRANSCRIBE_SPEECH_COMMAND_KEY}" with the platform "fileId" from the conversation (audio attachment hints in the user message tail).`,
15370
- '- If no audio file id is available, ask the user to attach an audio file before calling the tool.',
15557
+ `- When the user asks to transcribe attached audio or voice to text, you MUST call "${AIMANAGEMENT_CHAT_TRANSCRIBE_SPEECH_COMMAND_KEY}" with the platform "fileId" from the conversation (hints in the user message tail).`,
15558
+ '- If there is no audio file id, ask once to attach audio.',
15371
15559
  '',
15372
15560
  '## Text-to-speech',
15373
15561
  `- When the user asks for spoken audio, read-aloud, voice output, or TTS from text, you MUST call "${AIMANAGEMENT_CHAT_SYNTHESIZE_SPEECH_COMMAND_KEY}" with the exact "text" to speak.`,
15374
- '- Keep "text" within provider limits (e.g. OpenAI 4096 characters).',
15375
- '- After the tool returns, you may confirm briefly; the UI plays audio from the stored file id in the tool output.',
15562
+ '- Keep "text" within provider limits (e.g. OpenAI 4096 characters). After success, at most one short line; the UI plays audio from tool output.',
15376
15563
  ].join('\n');
15377
15564
  function appendSystemToolsHintIfNeeded(base, toolSchemaCount) {
15378
15565
  if (toolSchemaCount <= 0) {
@@ -15436,14 +15623,13 @@ function appendSupervisorAgentDelegationHint(base) {
15436
15623
  '### Tabular lists and forms',
15437
15624
  '- For **multiple similar items** (lists, catalogs, inventories), prefer a **rendered table** in chat: obtain rows from the right data specialist, then delegate to **widget-form-layout** so it emits a `table-layout` (scoped **Widgets:GetForAI** for `table-layout` / `table-item-layout` shapes).',
15438
15625
  '- For **labeled inputs** or a **mini-form** in chat, delegate to **widget-form-layout** using `form-field` wrappers and registry editors discovered via scoped **Widgets:GetForAI**.',
15439
- '- For **dashboard chart** tiles (bar, line, donut, gauge, funnel, heatmap), delegate to **widget-chart-layout**.',
15440
- '- For **dashboard KPI, weather, clocks, shortcuts, sticky notes**, delegate to **widget-dashboard-layout**.',
15441
- '- Use **multiple agent calls** in one turn when needed (data first, layout second).',
15626
+ '- For **charts** (bar, line, donut, gauge, funnel, heatmap), delegate to **widget-chart-layout**.',
15627
+ '- Use **multiple agent calls** in one turn when needed (data first, chart second).',
15442
15628
  '',
15443
15629
  '### Widget specialists (layout JSON)',
15444
- '- When a delegated **widget-form-layout**, **widget-chart-layout**, or **widget-dashboard-layout** agent returns a widget tree in `data.answer`, your final assistant reply MUST be exactly one JSON object (no markdown fences):',
15630
+ '- When a delegated **widget-form-layout** or **widget-chart-layout** agent returns a widget tree under `data.responses` (a `node` segment), your final assistant reply MUST include exactly one JSON object per such node (no markdown fences):',
15445
15631
  ' `{"type":"node","content": <AXPWidgetNode>}`',
15446
- '- Parse `data.answer` if it is a string; use the resulting object as `content` when it is already a bare AXPWidgetNode root.',
15632
+ '- If the specialist returns a `text` segment in `data.responses`, mirror that prose verbatim when policy requires a relay; for `file` segments the UI replays storage ids — do not drop them from your synthesis when the user should see that media.',
15447
15633
  '- Do not send only the inner widget JSON as normal chat text — the UI requires this envelope to render layout as a distinct message type.',
15448
15634
  ].join('\n');
15449
15635
  return base.trim() ? `${base.trim()}\n\n${block}` : block;
@@ -15470,33 +15656,27 @@ function formatTranscriptTailLineForMessage(m) {
15470
15656
  let text = axpAiChatMessageGetText(m);
15471
15657
  if (role === 'user') {
15472
15658
  const imageHints = [];
15473
- for (const r of m.responses) {
15474
- if (r.type === 'image') {
15475
- const id = r.content.fileId?.trim() ?? '';
15476
- if (id) {
15477
- const name = r.content.name?.trim();
15478
- imageHints.push(name ? `fileId=${id} name=${name}` : `fileId=${id}`);
15479
- }
15480
- }
15481
- }
15482
15659
  const audioHints = [];
15483
- for (const r of m.responses) {
15484
- if (r.type === 'audio') {
15485
- const id = r.content.fileId?.trim() ?? '';
15486
- if (id) {
15487
- const name = r.content.name?.trim();
15488
- audioHints.push(name ? `fileId=${id} name=${name}` : `fileId=${id}`);
15489
- }
15490
- }
15491
- }
15492
15660
  const fileHints = [];
15493
15661
  for (const r of m.responses) {
15494
- if (r.type === 'file') {
15495
- const id = r.content.fileId?.trim() ?? '';
15496
- if (id) {
15497
- const name = r.content.name?.trim();
15498
- fileHints.push(name ? `fileId=${id} name=${name}` : `fileId=${id}`);
15499
- }
15662
+ if (r.type !== 'file') {
15663
+ continue;
15664
+ }
15665
+ const id = r.content.fileId?.trim() ?? '';
15666
+ if (!id) {
15667
+ continue;
15668
+ }
15669
+ const name = r.content.name?.trim();
15670
+ const hint = name ? `fileId=${id} name=${name}` : `fileId=${id}`;
15671
+ const mime = r.content.mimeType?.trim().toLowerCase() ?? '';
15672
+ if (mime.startsWith('image/')) {
15673
+ imageHints.push(hint);
15674
+ }
15675
+ else if (mime.startsWith('audio/')) {
15676
+ audioHints.push(hint);
15677
+ }
15678
+ else {
15679
+ fileHints.push(hint);
15500
15680
  }
15501
15681
  }
15502
15682
  const extras = [];
@@ -15798,27 +15978,6 @@ function agentAsAssistScope(agent) {
15798
15978
  queryIds: agent.queryIds,
15799
15979
  };
15800
15980
  }
15801
- function collectDelegatedAgentAnswer(msgs) {
15802
- const texts = [];
15803
- for (const m of msgs) {
15804
- if (m.role === 'assistant' && !axpAiChatMessageIsDelegatedReflectionExcluded(m)) {
15805
- let t = axpAiChatMessageGetText(m).trim();
15806
- if (!t.length) {
15807
- const thinkParts = [];
15808
- for (const r of m.responses) {
15809
- if (r.type === 'think' && typeof r.content === 'string' && r.content.trim().length > 0) {
15810
- thinkParts.push(r.content.trim());
15811
- }
15812
- }
15813
- t = thinkParts.join('\n\n').trim();
15814
- }
15815
- if (t.length > 0) {
15816
- texts.push(t);
15817
- }
15818
- }
15819
- }
15820
- return texts.join('\n\n').trim();
15821
- }
15822
15981
  //#endregion
15823
15982
 
15824
15983
  //#region ---- Imports ----
@@ -15834,7 +15993,7 @@ async function buildAiChatImageBase64Cache(fileStorage, messages) {
15834
15993
  continue;
15835
15994
  }
15836
15995
  for (const r of m.responses) {
15837
- if (r.type === 'image' || r.type === 'file') {
15996
+ if (r.type === 'file') {
15838
15997
  const id = r.content.fileId.trim();
15839
15998
  if (id) {
15840
15999
  ids.add(id);
@@ -16509,29 +16668,6 @@ function appendOpenAiUserResponsePart(r, parts, imageCache) {
16509
16668
  parts.push({ type: 'text', text: r.content });
16510
16669
  }
16511
16670
  }
16512
- else if (r.type === 'image') {
16513
- const id = r.content.fileId.trim();
16514
- const resolved = imageCache.get(id);
16515
- if (!resolved) {
16516
- throw new Error(`Could not resolve chat image for OpenAI request (fileId: ${id}).`);
16517
- }
16518
- parts.push({
16519
- type: 'image_url',
16520
- image_url: {
16521
- url: `data:${resolved.mimeType};base64,${resolved.base64}`,
16522
- },
16523
- });
16524
- }
16525
- else if (r.type === 'audio') {
16526
- const id = r.content.fileId.trim();
16527
- const name = r.content.name?.trim();
16528
- parts.push({
16529
- type: 'text',
16530
- text: name
16531
- ? `[Audio attachment: fileId=${id} name=${name}]`
16532
- : `[Audio attachment: fileId=${id}]`,
16533
- });
16534
- }
16535
16671
  else if (r.type === 'file') {
16536
16672
  const id = r.content.fileId.trim();
16537
16673
  const resolved = imageCache.get(id);
@@ -16540,6 +16676,25 @@ function appendOpenAiUserResponsePart(r, parts, imageCache) {
16540
16676
  }
16541
16677
  const mime = resolved.mimeType.trim().toLowerCase();
16542
16678
  const rawName = r.content.name?.trim();
16679
+ const displayName = rawName && rawName.length > 0 ? rawName : undefined;
16680
+ if (mime.startsWith('image/')) {
16681
+ parts.push({
16682
+ type: 'image_url',
16683
+ image_url: {
16684
+ url: `data:${resolved.mimeType};base64,${resolved.base64}`,
16685
+ },
16686
+ });
16687
+ return;
16688
+ }
16689
+ if (mime.startsWith('audio/')) {
16690
+ parts.push({
16691
+ type: 'text',
16692
+ text: displayName
16693
+ ? `[Audio attachment: fileId=${id} name=${displayName}]`
16694
+ : `[Audio attachment: fileId=${id}]`,
16695
+ });
16696
+ return;
16697
+ }
16543
16698
  const filename = rawName && rawName.length > 0 ? rawName : 'attachment';
16544
16699
  if (openAiUserFileShouldInlineAsText(mime)) {
16545
16700
  const decoded = decodeUtf8FromBase64(resolved.base64);
@@ -16596,7 +16751,7 @@ function openAiUserMessageNeedsMultipartContent(m) {
16596
16751
  return false;
16597
16752
  }
16598
16753
  return (m.responses.length > 1 ||
16599
- m.responses.some((r) => r.type === 'image' || r.type === 'audio' || r.type === 'file' || r.type === 'node'));
16754
+ m.responses.some((r) => r.type === 'file' || r.type === 'node'));
16600
16755
  }
16601
16756
  /**
16602
16757
  * Builds one OpenAI `assistant` message from consecutive platform assistant lines (text / node / tool).
@@ -16687,23 +16842,21 @@ function toOpenAiChatCompletionMessage(m, toOpenAiToolName, imageCache) {
16687
16842
  ? r0.content
16688
16843
  : r0?.type === 'node'
16689
16844
  ? JSON.stringify({ type: 'node', content: r0.content })
16690
- : r0?.type === 'audio'
16845
+ : r0?.type === 'file'
16691
16846
  ? (() => {
16692
16847
  const id = r0.content.fileId.trim();
16693
16848
  const name = r0.content.name?.trim();
16849
+ const mime = r0.content.mimeType?.trim().toLowerCase() ?? '';
16850
+ if (mime.startsWith('audio/')) {
16851
+ return name
16852
+ ? `[Audio attachment: fileId=${id} name=${name}]`
16853
+ : `[Audio attachment: fileId=${id}]`;
16854
+ }
16694
16855
  return name
16695
- ? `[Audio attachment: fileId=${id} name=${name}]`
16696
- : `[Audio attachment: fileId=${id}]`;
16856
+ ? `[File attachment: fileId=${id} name=${name}]`
16857
+ : `[File attachment: fileId=${id}]`;
16697
16858
  })()
16698
- : r0?.type === 'file'
16699
- ? (() => {
16700
- const id = r0.content.fileId.trim();
16701
- const name = r0.content.name?.trim();
16702
- return name
16703
- ? `[File attachment: fileId=${id} name=${name}]`
16704
- : `[File attachment: fileId=${id}]`;
16705
- })()
16706
- : '';
16859
+ : '';
16707
16860
  return {
16708
16861
  role: m.role,
16709
16862
  content: text,
@@ -17071,34 +17224,23 @@ function appendGeminiUserResponsePart(r, parts, imageCache) {
17071
17224
  parts.push({ text: r.content });
17072
17225
  }
17073
17226
  }
17074
- else if (r.type === 'image') {
17075
- const id = r.content.fileId.trim();
17076
- const resolved = imageCache.get(id);
17077
- if (!resolved) {
17078
- throw new Error(`Could not resolve chat image for Gemini request (fileId: ${id}).`);
17079
- }
17080
- parts.push({
17081
- inline_data: {
17082
- mime_type: resolved.mimeType,
17083
- data: resolved.base64,
17084
- },
17085
- });
17086
- }
17087
- else if (r.type === 'audio') {
17088
- const id = r.content.fileId.trim();
17089
- const name = r.content.name?.trim();
17090
- parts.push({
17091
- text: name
17092
- ? `[Audio attachment: fileId=${id} name=${name}]`
17093
- : `[Audio attachment: fileId=${id}]`,
17094
- });
17095
- }
17096
17227
  else if (r.type === 'file') {
17097
17228
  const id = r.content.fileId.trim();
17098
17229
  const resolved = imageCache.get(id);
17099
17230
  if (!resolved) {
17100
17231
  throw new Error(`Could not resolve chat file for Gemini request (fileId: ${id}).`);
17101
17232
  }
17233
+ const mime = resolved.mimeType.trim().toLowerCase();
17234
+ const rawName = r.content.name?.trim();
17235
+ const displayName = rawName && rawName.length > 0 ? rawName : undefined;
17236
+ if (mime.startsWith('audio/')) {
17237
+ parts.push({
17238
+ text: displayName
17239
+ ? `[Audio attachment: fileId=${id} name=${displayName}]`
17240
+ : `[Audio attachment: fileId=${id}]`,
17241
+ });
17242
+ return;
17243
+ }
17102
17244
  parts.push({
17103
17245
  inline_data: {
17104
17246
  mime_type: resolved.mimeType,
@@ -17117,7 +17259,7 @@ function geminiUserMessageNeedsParts(message) {
17117
17259
  return false;
17118
17260
  }
17119
17261
  return (message.responses.length > 1 ||
17120
- message.responses.some((r) => r.type === 'image' || r.type === 'audio' || r.type === 'file' || r.type === 'node'));
17262
+ message.responses.some((r) => r.type === 'file' || r.type === 'node'));
17121
17263
  }
17122
17264
  /**
17123
17265
  * Maps platform messages (after system filter) to one Gemini `contents` entry.
@@ -17184,23 +17326,21 @@ function mapPlatformMessageToGeminiContent(message, imageCache) {
17184
17326
  ? r0.content
17185
17327
  : r0?.type === 'node'
17186
17328
  ? JSON.stringify({ type: 'node', content: r0.content })
17187
- : r0?.type === 'audio'
17329
+ : r0?.type === 'file'
17188
17330
  ? (() => {
17189
17331
  const id = r0.content.fileId.trim();
17190
17332
  const name = r0.content.name?.trim();
17333
+ const mime = r0.content.mimeType?.trim().toLowerCase() ?? '';
17334
+ if (mime.startsWith('audio/')) {
17335
+ return name
17336
+ ? `[Audio attachment: fileId=${id} name=${name}]`
17337
+ : `[Audio attachment: fileId=${id}]`;
17338
+ }
17191
17339
  return name
17192
- ? `[Audio attachment: fileId=${id} name=${name}]`
17193
- : `[Audio attachment: fileId=${id}]`;
17340
+ ? `[File attachment: fileId=${id} name=${name}]`
17341
+ : `[File attachment: fileId=${id}]`;
17194
17342
  })()
17195
- : r0?.type === 'file'
17196
- ? (() => {
17197
- const id = r0.content.fileId.trim();
17198
- const name = r0.content.name?.trim();
17199
- return name
17200
- ? `[File attachment: fileId=${id} name=${name}]`
17201
- : `[File attachment: fileId=${id}]`;
17202
- })()
17203
- : '';
17343
+ : '';
17204
17344
  return {
17205
17345
  role: 'user',
17206
17346
  parts: [{ text: userText }],
@@ -17515,7 +17655,7 @@ class AXCAiChatDemisProvider {
17515
17655
  continue;
17516
17656
  }
17517
17657
  for (const r of m.responses) {
17518
- if (r.type === 'audio') {
17658
+ if (r.type === 'file' && r.content.mimeType?.trim().toLowerCase().startsWith('audio/')) {
17519
17659
  throw new Error('Demis (Demisco) chat transport does not support audio attachments.');
17520
17660
  }
17521
17661
  }
@@ -17700,7 +17840,7 @@ class AXCAiChatDemisProvider {
17700
17840
  }
17701
17841
  const out = [];
17702
17842
  for (const r of lastUser.responses) {
17703
- if (r.type !== 'file' && r.type !== 'image') {
17843
+ if (r.type !== 'file') {
17704
17844
  continue;
17705
17845
  }
17706
17846
  const fileId = r.content.fileId?.trim();
@@ -18540,10 +18680,11 @@ class AXCAiEngine extends AXPAiEngine {
18540
18680
  typeof o['data'] === 'object' &&
18541
18681
  !Array.isArray(o['data'])) {
18542
18682
  const d = o['data'];
18543
- const data = {};
18544
- if (typeof d['answer'] === 'string') {
18545
- data.answer = d['answer'];
18683
+ const parsedResponses = axpAiParseDelegatedAgentResultSegmentsFromUnknown(d['responses']);
18684
+ if (parsedResponses.length === 0) {
18685
+ return axpAiChatAgentResultMessage(call.id, { success: false, error: 'Delegated agent result is missing data.responses.' }, call.name);
18546
18686
  }
18687
+ const data = { responses: parsedResponses };
18547
18688
  if (typeof d['agentName'] === 'string' && d['agentName'].trim()) {
18548
18689
  data.agentName = d['agentName'].trim();
18549
18690
  }
@@ -18716,8 +18857,13 @@ class AXCAiEngine extends AXPAiEngine {
18716
18857
  }
18717
18858
  }
18718
18859
  }
18719
- const answer = collectDelegatedAgentAnswer(subMessages);
18720
- if (!answer.trim() && isDevMode()) {
18860
+ subMessages = axpAiDelegatedSubTranscriptAppendFileArtifactFromToolResults(subMessages);
18861
+ let responses = axpAiCollectDelegatedAgentOutcomeResponses(subMessages);
18862
+ if (responses.length === 0) {
18863
+ responses = [{ type: 'text', content: '(no specialist output returned)' }];
18864
+ }
18865
+ const outcomePlain = axpAiDelegatedAgentOutcomeResponsesPlainText(responses);
18866
+ if (!outcomePlain.trim() && !responses.some((s) => s.type === 'file' || s.type === 'node') && isDevMode()) {
18721
18867
  const nonReflectionAssistants = subMessages.filter((m) => m.role === 'assistant' && !axpAiChatMessageIsDelegatedReflectionExcluded(m));
18722
18868
  const reflectionAssistants = subMessages.filter((m) => m.role === 'assistant' && axpAiChatMessageIsDelegatedReflectionExcluded(m));
18723
18869
  const lastToolJsonApproxLen = (() => {
@@ -18735,7 +18881,7 @@ class AXCAiEngine extends AXPAiEngine {
18735
18881
  }
18736
18882
  return undefined;
18737
18883
  })();
18738
- console.warn('[AXCAiEngine mock] Delegated agent finished with no user-visible answer text.', {
18884
+ console.warn('[AXCAiEngine mock] Delegated agent finished with no user-visible outcome segments.', {
18739
18885
  agentId: agent.id,
18740
18886
  agentName: axcResolveAiMlOrPlainString(agent.name, 'en-US') || agent.name,
18741
18887
  assistantMessageCount: nonReflectionAssistants.length,
@@ -18744,7 +18890,7 @@ class AXCAiEngine extends AXPAiEngine {
18744
18890
  reflectionPlainTextCount: reflectionAssistants.filter((m) => axpAiChatMessageGetText(m).trim().length > 0).length,
18745
18891
  transcriptTailRoles: subMessages.slice(-8).map((m) => m.role),
18746
18892
  lastToolMessageJsonApproxChars: lastToolJsonApproxLen,
18747
- hint: 'Not an HTTP error: the OpenAI-compatible API returned 200 but no final assistant text/think was collected. Common causes: local model stops after tool_calls without a follow-up message; oversized tool JSON (context truncation); or reflection text exists but is excluded from this answer field — see collectDelegatedAgentAnswer / delegatedReflection.',
18893
+ hint: 'Not an HTTP error: the OpenAI-compatible API returned 200 but no text/file/node segments were collected for data.responses. See axpAiCollectDelegatedAgentOutcomeResponses / delegatedReflection.',
18748
18894
  });
18749
18895
  }
18750
18896
  return {
@@ -18753,7 +18899,7 @@ class AXCAiEngine extends AXPAiEngine {
18753
18899
  data: {
18754
18900
  agentId: agent.id,
18755
18901
  agentName: agent.name,
18756
- answer: answer || '(no assistant text returned)',
18902
+ responses,
18757
18903
  },
18758
18904
  },
18759
18905
  usageTotals: acc,
@@ -18844,13 +18990,13 @@ class AXCAiEngine extends AXPAiEngine {
18844
18990
  filter: {
18845
18991
  field: 'name',
18846
18992
  operator: { type: 'equal' },
18847
- value: 'platform-default',
18993
+ value: 'platform-assistant',
18848
18994
  },
18849
18995
  });
18850
18996
  const items = (queryResult?.items ?? []);
18851
18997
  const record = items[0];
18852
18998
  if (!record) {
18853
- throw new Error('No default assist is configured. Create an assist named "platform-default" or select one under AI Settings.');
18999
+ throw new Error('No default assist is configured. Create an assist named "platform-assistant" or select one under AI Settings.');
18854
19000
  }
18855
19001
  return record;
18856
19002
  }
@@ -19128,7 +19274,7 @@ class AXCAiManagementMockModule {
19128
19274
  provideCommandSetups([
19129
19275
  {
19130
19276
  key: 'AiManagement:ChatGenerateImage',
19131
- command: () => import('./acorex-connectivity-mock-chat-generate-image.command-D_2bFiuO.mjs').then((c) => c.AiManagementChatGenerateImageCommand),
19277
+ command: () => import('./acorex-connectivity-mock-chat-generate-image.command-IUvQRJU0.mjs').then((c) => c.AiManagementChatGenerateImageCommand),
19132
19278
  },
19133
19279
  {
19134
19280
  key: 'AiManagement:ExtractDocumentText',
@@ -19140,11 +19286,11 @@ class AXCAiManagementMockModule {
19140
19286
  },
19141
19287
  {
19142
19288
  key: 'AiManagement:ChatTranscribeSpeech',
19143
- command: () => import('./acorex-connectivity-mock-chat-transcribe-speech.command-B1PpdDkQ.mjs').then((c) => c.AiManagementChatTranscribeSpeechCommand),
19289
+ command: () => import('./acorex-connectivity-mock-chat-transcribe-speech.command-Cr0QRiqr.mjs').then((c) => c.AiManagementChatTranscribeSpeechCommand),
19144
19290
  },
19145
19291
  {
19146
19292
  key: 'AiManagement:ChatSynthesizeSpeech',
19147
- command: () => import('./acorex-connectivity-mock-chat-synthesize-speech.command-CWK6lBgb.mjs').then((c) => c.AiManagementChatSynthesizeSpeechCommand),
19293
+ command: () => import('./acorex-connectivity-mock-chat-synthesize-speech.command-DE8YU17E.mjs').then((c) => c.AiManagementChatSynthesizeSpeechCommand),
19148
19294
  },
19149
19295
  ]),
19150
19296
  ] }); }
@@ -19187,7 +19333,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
19187
19333
  provideCommandSetups([
19188
19334
  {
19189
19335
  key: 'AiManagement:ChatGenerateImage',
19190
- command: () => import('./acorex-connectivity-mock-chat-generate-image.command-D_2bFiuO.mjs').then((c) => c.AiManagementChatGenerateImageCommand),
19336
+ command: () => import('./acorex-connectivity-mock-chat-generate-image.command-IUvQRJU0.mjs').then((c) => c.AiManagementChatGenerateImageCommand),
19191
19337
  },
19192
19338
  {
19193
19339
  key: 'AiManagement:ExtractDocumentText',
@@ -19199,11 +19345,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
19199
19345
  },
19200
19346
  {
19201
19347
  key: 'AiManagement:ChatTranscribeSpeech',
19202
- command: () => import('./acorex-connectivity-mock-chat-transcribe-speech.command-B1PpdDkQ.mjs').then((c) => c.AiManagementChatTranscribeSpeechCommand),
19348
+ command: () => import('./acorex-connectivity-mock-chat-transcribe-speech.command-Cr0QRiqr.mjs').then((c) => c.AiManagementChatTranscribeSpeechCommand),
19203
19349
  },
19204
19350
  {
19205
19351
  key: 'AiManagement:ChatSynthesizeSpeech',
19206
- command: () => import('./acorex-connectivity-mock-chat-synthesize-speech.command-CWK6lBgb.mjs').then((c) => c.AiManagementChatSynthesizeSpeechCommand),
19352
+ command: () => import('./acorex-connectivity-mock-chat-synthesize-speech.command-DE8YU17E.mjs').then((c) => c.AiManagementChatSynthesizeSpeechCommand),
19207
19353
  },
19208
19354
  ]),
19209
19355
  ],
@@ -24002,25 +24148,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
24002
24148
 
24003
24149
  const CATEGORY_ENTITY = 'AssetManagement.ManualAssetCategory';
24004
24150
  const ASSET_TYPE_ENTITY = 'AssetManagement.AssetType';
24005
- const resolveAssetTypeCodeForCreate = async (data, backend) => {
24006
- const result = await backend.query(ASSET_TYPE_ENTITY, { skip: 0, take: 5000 });
24007
- const items = result?.items ?? [];
24008
- const maxCode = items.reduce((m, row) => (typeof row?.code === 'number' && row.code > m ? row.code : m), 0);
24009
- const nextCode = maxCode + 1;
24010
- const raw = data?.['code'];
24011
- if (raw === undefined || raw === null) {
24012
- return { ...data, ['code']: nextCode };
24013
- }
24014
- const numeric = typeof raw === 'number' ? raw : Number(raw);
24015
- if (Number.isNaN(numeric)) {
24016
- return { ...data, ['code']: nextCode };
24017
- }
24018
- const duplicate = items.some((row) => row?.code === numeric);
24019
- if (duplicate) {
24020
- return { ...data, ['code']: nextCode };
24021
- }
24022
- return data;
24023
- };
24024
24151
  /**
24025
24152
  * Collects maintenanceTypeIds by traversing a category and its parent hierarchy.
24026
24153
  */
@@ -24112,15 +24239,6 @@ const enrichAsset = async (asset, backend) => {
24112
24239
  return { ...asset, hasMaintenance: false, availableMaintenanceTypeIds: [] };
24113
24240
  }
24114
24241
  };
24115
- const assetTypeCreateCodeMiddleware = {
24116
- target: { entity: ASSET_TYPE_ENTITY, ops: ['create'], order: 85 },
24117
- execute: async (ctx, next) => {
24118
- if (ctx.data && typeof ctx.data === 'object') {
24119
- ctx.data = (await resolveAssetTypeCodeForCreate(ctx.data, ctx.backend));
24120
- }
24121
- await next();
24122
- },
24123
- };
24124
24242
  const assetManagementMiddleware = {
24125
24243
  target: { entity: 'AssetManagement.Asset', ops: ['create', 'update', 'getOne', 'query'], order: 90 },
24126
24244
  execute: async (ctx, next) => {
@@ -24233,8 +24351,12 @@ const ASSET_TYPE_CATEGORY_MOCK = [
24233
24351
  const assetTypeMock = [
24234
24352
  {
24235
24353
  id: MOCK_ASSET_TYPE_IT_EQUIPMENT_ID,
24236
- /** Identifier rule `asset-type-code`: `AST-{seq:2}` (seq padded to 2 digits). */
24237
- code: 'AST-01',
24354
+ /**
24355
+ * Identifier rule `asset-type-code`: `AST-{seq:4}`. Seed uses a high sequence band (90+)
24356
+ * so `identifier.peek("asset-type-code")` on a fresh Dexie store (starts at AST-0001) does not
24357
+ * collide with `unique-fields` on create (same pattern as asset mock codes).
24358
+ */
24359
+ code: 'AST-0090',
24238
24360
  name: 'it_equipment',
24239
24361
  title: ml$4('IT Equipment', 'تجهیزات فناوری اطلاعات'),
24240
24362
  description: ml$4('Endpoint devices and office IT hardware', 'دستگاه‌های کاربری و سخت‌افزار IT اداری'),
@@ -24354,7 +24476,7 @@ const assetTypeMock = [
24354
24476
  },
24355
24477
  {
24356
24478
  id: MOCK_ASSET_TYPE_FACILITY_SYSTEMS_ID,
24357
- code: 'AST-02',
24479
+ code: 'AST-0091',
24358
24480
  name: 'facility_systems',
24359
24481
  title: ml$4('Facility Systems', 'سیستم‌های تاسیساتی'),
24360
24482
  description: ml$4('Mechanical and utility assets', 'دارایی‌های مکانیکی و خدماتی'),
@@ -24460,7 +24582,7 @@ const assetTypeMock = [
24460
24582
  },
24461
24583
  {
24462
24584
  id: MOCK_ASSET_TYPE_FLEET_MOBILE_ID,
24463
- code: 'AST-03',
24585
+ code: 'AST-0092',
24464
24586
  name: 'fleet_mobile_equipment',
24465
24587
  title: ml$4('Fleet & Mobile Equipment', 'ناوگان و تجهیزات متحرک'),
24466
24588
  description: ml$4('Vehicles and mobile operation assets', 'دارایی‌های خودرو و عملیات متحرک'),
@@ -27151,7 +27273,11 @@ if (locationMock.length >= 15) {
27151
27273
  }
27152
27274
 
27153
27275
  const uuid$o = AXPDataGenerator.uuid;
27154
- /** Seeded `code` values match identifier rule `asset-system-type-code`: `ASYS-{seq:2}`. */
27276
+ /**
27277
+ * Identifier rule `asset-system-type-code`: `ASYS-{seq:2}`. Seed uses a high sequence band (90+)
27278
+ * so `identifier.peek("asset-system-type-code")` on a fresh store (starts at ASYS-01) does not
27279
+ * collide with seeded rows under the `unique-fields` plugin on `code`.
27280
+ */
27155
27281
  const MOCK_ASSET_SYSTEM_TYPE_IT_ID = 'asset-system-type-it';
27156
27282
  const MOCK_ASSET_SYSTEM_TYPE_FACILITY_ID = 'asset-system-type-facility';
27157
27283
  const MOCK_ASSET_SYSTEM_TYPE_FLEET_ID = 'asset-system-type-fleet';
@@ -27163,7 +27289,7 @@ const ml$1 = (enUS, faIR) => ({
27163
27289
  const assetSystemTypeMock = [
27164
27290
  {
27165
27291
  id: MOCK_ASSET_SYSTEM_TYPE_IT_ID,
27166
- code: 'ASYS-01',
27292
+ code: 'ASYS-90',
27167
27293
  title: ml$1('IT System Type', 'نوع سیستم فناوری اطلاعات'),
27168
27294
  description: ml$1('Technology systems including servers, networks, and user endpoints.', 'سیستم‌های فناوری شامل سرورها، شبکه‌ها و تجهیزات کاربری.'),
27169
27295
  metaDataList: { groups: [] },
@@ -27171,7 +27297,7 @@ const assetSystemTypeMock = [
27171
27297
  },
27172
27298
  {
27173
27299
  id: MOCK_ASSET_SYSTEM_TYPE_FACILITY_ID,
27174
- code: 'ASYS-02',
27300
+ code: 'ASYS-91',
27175
27301
  title: ml$1('Facility System Type', 'نوع سیستم تاسیسات'),
27176
27302
  description: ml$1('Building and utility systems such as HVAC, power, and safety.', 'سیستم‌های ساختمانی و خدماتی مانند HVAC، برق و ایمنی.'),
27177
27303
  metaDataList: { groups: [] },
@@ -27179,7 +27305,7 @@ const assetSystemTypeMock = [
27179
27305
  },
27180
27306
  {
27181
27307
  id: MOCK_ASSET_SYSTEM_TYPE_FLEET_ID,
27182
- code: 'ASYS-03',
27308
+ code: 'ASYS-92',
27183
27309
  title: ml$1('Fleet System Type', 'نوع سیستم ناوگان'),
27184
27310
  description: ml$1('Vehicle and mobile equipment systems used in operations.', 'سیستم‌های خودرو و تجهیزات متحرک مورد استفاده در عملیات.'),
27185
27311
  hasChild: false,
@@ -27187,7 +27313,7 @@ const assetSystemTypeMock = [
27187
27313
  },
27188
27314
  {
27189
27315
  id: MOCK_ASSET_SYSTEM_TYPE_COMPUTE_ID,
27190
- code: 'ASYS-04',
27316
+ code: 'ASYS-93',
27191
27317
  title: ml$1('Compute Subsystem Type', 'نوع زیرسیستم رایانشی'),
27192
27318
  description: ml$1('Subsystem classification for compute-oriented asset groups.', 'طبقه‌بندی زیرسیستم برای گروه‌های دارایی مبتنی بر رایانش.'),
27193
27319
  parentId: MOCK_ASSET_SYSTEM_TYPE_IT_ID,
@@ -27200,7 +27326,7 @@ const assetSystemTypeMock = [
27200
27326
  },
27201
27327
  {
27202
27328
  id: uuid$o(),
27203
- code: 'ASYS-05',
27329
+ code: 'ASYS-94',
27204
27330
  title: ml$1('Power Distribution Subsystem Type', 'نوع زیرسیستم توزیع برق'),
27205
27331
  description: ml$1('Subsystem classification for electrical distribution and backup power.', 'طبقه‌بندی زیرسیستم برای توزیع برق و برق پشتیبان.'),
27206
27332
  parentId: MOCK_ASSET_SYSTEM_TYPE_FACILITY_ID,
@@ -31870,7 +31996,6 @@ class AXCAssetManagementMockModule {
31870
31996
  { provide: AXP_DATA_SEEDER_TOKEN, useClass: AXCAssetTypeSeeder, multi: true },
31871
31997
  { provide: AXP_DATA_SEEDER_TOKEN, useClass: AXCAssetTypeSectionSeeder, multi: true },
31872
31998
  { provide: AXP_DATA_SEEDER_TOKEN, useClass: AXCAssetTypeSectionComponentSeeder, multi: true },
31873
- { provide: AXP_ENTITY_STORAGE_MIDDLEWARE, multi: true, useValue: assetTypeCreateCodeMiddleware },
31874
31999
  { provide: AXP_ENTITY_STORAGE_MIDDLEWARE, multi: true, useValue: assetManagementMiddleware },
31875
32000
  ] }); }
31876
32001
  }
@@ -31884,7 +32009,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
31884
32009
  { provide: AXP_DATA_SEEDER_TOKEN, useClass: AXCAssetTypeSeeder, multi: true },
31885
32010
  { provide: AXP_DATA_SEEDER_TOKEN, useClass: AXCAssetTypeSectionSeeder, multi: true },
31886
32011
  { provide: AXP_DATA_SEEDER_TOKEN, useClass: AXCAssetTypeSectionComponentSeeder, multi: true },
31887
- { provide: AXP_ENTITY_STORAGE_MIDDLEWARE, multi: true, useValue: assetTypeCreateCodeMiddleware },
31888
32012
  { provide: AXP_ENTITY_STORAGE_MIDDLEWARE, multi: true, useValue: assetManagementMiddleware },
31889
32013
  ],
31890
32014
  }]
@@ -36886,231 +37010,18 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
36886
37010
  }]
36887
37011
  }] });
36888
37012
 
36889
- //#endregion
36890
- //#region ---- Service ----
37013
+ //#region ---- Shared storage hydration ----
36891
37014
  /**
36892
- * Mock implementation of AXMChatUserApi using conversation shared storage.
36893
- * Provides user profile, discovery, presence, blocking, and settings operations.
37015
+ * Ensures `conversationSharedStorage` is merged from IndexedDB before reads.
37016
+ * Deduplicates concurrent calls so the first `getMessages` / `getConversation` during
37017
+ * startup does not race ahead of mock realtime `connect()` (which also loads IndexedDB).
36894
37018
  */
36895
- class AXCConversationMockUserApi extends AXMChatUserApi {
36896
- //#region ---- User Profile ----
36897
- async getCurrentUser() {
36898
- const user = conversationSharedStorage.participants.get(conversationSharedStorage.currentUserId);
36899
- if (!user) {
36900
- throw this.createError('USER_NOT_FOUND', 'Current user not found', 404);
36901
- }
36902
- return user;
36903
- }
36904
- async updateProfile(updates) {
36905
- const user = await this.getCurrentUser();
36906
- return { ...user, ...updates };
36907
- }
36908
- async uploadAvatar(file) {
36909
- return new Promise((resolve) => {
36910
- const reader = new FileReader();
36911
- reader.onloadend = () => resolve(reader.result);
36912
- reader.readAsDataURL(file);
36913
- });
36914
- }
36915
- //#endregion
36916
- //#region ---- User Discovery ----
36917
- async getUsers(filters) {
36918
- const users = Array.from(conversationSharedStorage.participants.values());
36919
- const filtered = users.filter((u) => u.id !== conversationSharedStorage.currentUserId && !axmIsAssistPeerParticipant(u));
36920
- if (!filters?.query)
36921
- return filtered;
36922
- const q = filters.query.toLowerCase();
36923
- ``;
36924
- return filtered.filter((u) => {
36925
- const name = u.name.toLowerCase();
36926
- const desc = (u.description ?? '').toLowerCase();
36927
- return name.includes(q) || desc.includes(q);
36928
- });
36929
- }
36930
- async searchUsers(query) {
36931
- return this.getUsers({ query });
36932
- }
36933
- async getUserById(userId) {
36934
- const user = conversationSharedStorage.participants.get(userId);
36935
- if (!user) {
36936
- throw this.createError('USER_NOT_FOUND', `User ${userId} not found`, 404);
36937
- }
36938
- return user;
36939
- }
36940
- async getUsersByIds(userIds) {
36941
- return userIds
36942
- .map((id) => conversationSharedStorage.participants.get(id))
36943
- .filter((u) => u !== undefined);
36944
- }
36945
- //#endregion
36946
- //#region ---- Presence Management ----
36947
- async getUserPresence(userId) {
36948
- return {
36949
- userId,
36950
- status: 'online',
36951
- lastSeen: new Date(),
36952
- };
36953
- }
36954
- async updatePresence(_status, _statusText) {
36955
- await Promise.resolve();
36956
- }
36957
- //#endregion
36958
- //#region ---- User Blocking & Reporting ----
36959
- async blockUser(_userId, _reason) {
36960
- await Promise.resolve();
36961
- }
36962
- async unblockUser(_userId) {
36963
- await Promise.resolve();
36964
- }
36965
- async getBlockedUsers() {
36966
- return [];
36967
- }
36968
- async reportUser(_userId, _reason) {
36969
- await Promise.resolve();
36970
- }
36971
- //#endregion
36972
- //#region ---- User Settings & Preferences ----
36973
- async getUserSettings() {
36974
- return {
36975
- theme: 'light',
36976
- language: 'en',
36977
- notifications: true,
36978
- };
36979
- }
36980
- async updateUserSettings(_settings) {
36981
- await Promise.resolve();
36982
- }
36983
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXCConversationMockUserApi, deps: null, target: i0.ɵɵFactoryTarget.Injectable }); }
36984
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXCConversationMockUserApi }); }
37019
+ let sharedStorageHydration = null;
37020
+ function awaitConversationMockSharedStorage() {
37021
+ sharedStorageHydration ??= conversationSharedStorage.loadFromIndexedDB();
37022
+ return sharedStorageHydration;
36985
37023
  }
36986
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXCConversationMockUserApi, decorators: [{
36987
- type: Injectable
36988
- }] });
36989
-
36990
37024
  //#endregion
36991
- //#region ---- Service ----
36992
- /**
36993
- * Mock implementation of AXMChatRealtimeApi using conversation shared storage.
36994
- * Provides connection management and real-time event subscriptions.
36995
- */
36996
- class AXCConversationMockRealtimeApi extends AXMChatRealtimeApi {
36997
- constructor() {
36998
- super(...arguments);
36999
- //#region ---- Connection Status ----
37000
- this.connectionStatus$ = conversationSharedStorage.connectionStatus$;
37001
- }
37002
- //#endregion
37003
- //#region ---- Connection Management ----
37004
- async connect(_options) {
37005
- conversationSharedStorage.connectionStatus$.next('connecting');
37006
- await conversationSharedStorage.loadFromIndexedDB();
37007
- conversationSharedStorage.connectionStatus$.next('connected');
37008
- }
37009
- async disconnect() {
37010
- conversationSharedStorage.connectionStatus$.next('disconnected');
37011
- }
37012
- isConnected() {
37013
- return conversationSharedStorage.connectionStatus$.value === 'connected';
37014
- }
37015
- async reconnect() {
37016
- await this.disconnect();
37017
- await this.connect();
37018
- }
37019
- subscribeToConnectionEvents() {
37020
- return new Observable((subscriber) => {
37021
- subscriber.next({
37022
- type: 'connected',
37023
- timestamp: new Date(),
37024
- });
37025
- });
37026
- }
37027
- //#endregion
37028
- //#region ---- Message Events ----
37029
- subscribeToMessages(conversationId) {
37030
- return conversationSharedStorage.messageStream$.pipe(filter((msg) => msg.conversationId === conversationId));
37031
- }
37032
- subscribeToMessageUpdates(_conversationId) {
37033
- return conversationSharedStorage.messageUpdates$;
37034
- }
37035
- subscribeToMessageDeletions(_conversationId) {
37036
- return conversationSharedStorage.messageDeletions$;
37037
- }
37038
- subscribeToMessageReactions(_conversationId) {
37039
- return conversationSharedStorage.messageUpdates$;
37040
- }
37041
- //#endregion
37042
- //#region ---- Conversation Events ----
37043
- subscribeToConversationUpdates() {
37044
- return conversationSharedStorage.conversationUpdates$;
37045
- }
37046
- subscribeToConversationCreated() {
37047
- return new Observable(() => { });
37048
- }
37049
- subscribeToConversationDeleted() {
37050
- return new Observable(() => { });
37051
- }
37052
- //#endregion
37053
- //#region ---- Typing Indicators ----
37054
- subscribeToTypingIndicators(conversationId) {
37055
- if (!conversationId) {
37056
- return conversationSharedStorage.typingIndicators$;
37057
- }
37058
- return conversationSharedStorage.typingIndicators$.pipe(filter((ind) => ind.conversationId === conversationId));
37059
- }
37060
- //#endregion
37061
- //#region ---- Presence Updates ----
37062
- subscribeToPresenceUpdates(_userIds) {
37063
- return conversationSharedStorage.presenceUpdates$;
37064
- }
37065
- //#endregion
37066
- //#region ---- Read Receipts ----
37067
- subscribeToReadReceipts(_conversationId) {
37068
- return new Observable(() => { });
37069
- }
37070
- //#endregion
37071
- //#region ---- Notifications ----
37072
- subscribeToNotifications() {
37073
- return new Observable(() => { });
37074
- }
37075
- //#endregion
37076
- //#region ---- Call Events ----
37077
- subscribeToCallEvents() {
37078
- return new Observable(() => { });
37079
- }
37080
- //#endregion
37081
- //#region ---- User Events ----
37082
- subscribeToUserBlockEvents() {
37083
- return new Observable(() => { });
37084
- }
37085
- subscribeToParticipantEvents(_conversationId) {
37086
- return new Observable(() => { });
37087
- }
37088
- //#endregion
37089
- //#region ---- System Events ----
37090
- subscribeToSystemEvents() {
37091
- return new Observable(() => { });
37092
- }
37093
- //#endregion
37094
- //#region ---- Message Status Events ----
37095
- subscribeToMessageStatusChanges(_conversationId) {
37096
- return new Observable(() => { });
37097
- }
37098
- //#endregion
37099
- //#region ---- Conversation Settings Events ----
37100
- subscribeToConversationSettingsChanges(_conversationId) {
37101
- return new Observable(() => { });
37102
- }
37103
- //#endregion
37104
- //#region ---- Draft Events ----
37105
- subscribeToDraftChanges(_conversationId) {
37106
- return new Observable(() => { });
37107
- }
37108
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXCConversationMockRealtimeApi, deps: null, target: i0.ɵɵFactoryTarget.Injectable }); }
37109
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXCConversationMockRealtimeApi }); }
37110
- }
37111
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXCConversationMockRealtimeApi, decorators: [{
37112
- type: Injectable
37113
- }] });
37114
37025
 
37115
37026
  //#region ---- Assist metadata ----
37116
37027
  /**
@@ -37137,6 +37048,84 @@ function axcExtractAssistIdFromMetadata(metadata) {
37137
37048
  }
37138
37049
  //#endregion
37139
37050
 
37051
+ //#region ---- Imports ----
37052
+ //#endregion
37053
+ //#region ---- Unread rules ----
37054
+ /**
37055
+ * Whether an incoming message should increase the conversation unread counter in mock storage.
37056
+ * Streaming assist placeholders are excluded so the badge does not flicker while the user is in-thread.
37057
+ */
37058
+ function axcMockMessageCountsTowardUnread(message, currentUserId) {
37059
+ if (message.senderId === currentUserId) {
37060
+ return false;
37061
+ }
37062
+ if (message.status === 'read') {
37063
+ return false;
37064
+ }
37065
+ const meta = message.metadata;
37066
+ if (meta?.['isAssistResponse'] === true && meta?.['isStreaming'] === true) {
37067
+ return false;
37068
+ }
37069
+ return true;
37070
+ }
37071
+ function axcMockComputeConversationUnreadCount(conversationId) {
37072
+ const currentUserId = conversationSharedStorage.currentUserId;
37073
+ const ids = conversationSharedStorage.messagesByConversation.get(conversationId) ?? [];
37074
+ let unread = 0;
37075
+ for (const id of ids) {
37076
+ const m = conversationSharedStorage.messages.get(id);
37077
+ if (m && axcMockMessageCountsTowardUnread(m, currentUserId)) {
37078
+ unread++;
37079
+ }
37080
+ }
37081
+ return unread;
37082
+ }
37083
+ /**
37084
+ * Recomputes {@link AXConversation.unreadCount} from messages and notifies subscribers when it changes.
37085
+ */
37086
+ async function axcMockSyncConversationUnreadCount(conversationId) {
37087
+ const conversation = conversationSharedStorage.conversations.get(conversationId);
37088
+ if (!conversation) {
37089
+ return;
37090
+ }
37091
+ const unread = axcMockComputeConversationUnreadCount(conversationId);
37092
+ if (conversation.unreadCount === unread) {
37093
+ return;
37094
+ }
37095
+ const next = { ...conversation, unreadCount: unread };
37096
+ conversationSharedStorage.conversations.set(conversationId, next);
37097
+ await axConversationIndexedDbStorage.putConversation(next);
37098
+ conversationSharedStorage.conversationUpdates$.next(next);
37099
+ }
37100
+ /**
37101
+ * Marks non-current-user messages as read (by id) and syncs the conversation unread counter.
37102
+ * Returns ids that were actually transitioned to {@link AXMessage.status} `read` (for notifications).
37103
+ */
37104
+ async function axcMockMarkIncomingMessagesRead(conversationId, messageIds) {
37105
+ const currentUserId = conversationSharedStorage.currentUserId;
37106
+ const marked = [];
37107
+ for (const messageId of messageIds) {
37108
+ const message = conversationSharedStorage.messages.get(messageId);
37109
+ if (!message || message.conversationId !== conversationId) {
37110
+ continue;
37111
+ }
37112
+ if (message.senderId === currentUserId) {
37113
+ continue;
37114
+ }
37115
+ if (message.status === 'read') {
37116
+ continue;
37117
+ }
37118
+ message.status = 'read';
37119
+ conversationSharedStorage.messages.set(messageId, message);
37120
+ await axConversationIndexedDbStorage.putMessage(message);
37121
+ conversationSharedStorage.messageUpdates$.next(message);
37122
+ marked.push(messageId);
37123
+ }
37124
+ await axcMockSyncConversationUnreadCount(conversationId);
37125
+ return marked;
37126
+ }
37127
+ //#endregion
37128
+
37140
37129
  //#endregion
37141
37130
  //#region ---- Service ----
37142
37131
  /**
@@ -37149,6 +37138,7 @@ class AXCConversationMockConversationApi extends AXMChatConversationApi {
37149
37138
  constructor() {
37150
37139
  super(...arguments);
37151
37140
  this.translation = inject(AXTranslationService);
37141
+ this.notificationService = inject(AXMNotificationEntityService);
37152
37142
  }
37153
37143
  //#region ---- Conversation CRUD ----
37154
37144
  async createConversation(data) {
@@ -37201,6 +37191,7 @@ class AXCConversationMockConversationApi extends AXMChatConversationApi {
37201
37191
  return conversation;
37202
37192
  }
37203
37193
  async getConversation(conversationId) {
37194
+ await awaitConversationMockSharedStorage();
37204
37195
  const conversation = conversationSharedStorage.conversations.get(conversationId);
37205
37196
  if (!conversation) {
37206
37197
  throw this.createError('CONVERSATION_NOT_FOUND', 'Conversation not found', 404);
@@ -37208,6 +37199,7 @@ class AXCConversationMockConversationApi extends AXMChatConversationApi {
37208
37199
  return conversation;
37209
37200
  }
37210
37201
  async getConversations(pagination, _filters) {
37202
+ await awaitConversationMockSharedStorage();
37211
37203
  const items = Array.from(conversationSharedStorage.conversations.values()).sort((a, b) => b.lastMessageAt.getTime() - a.lastMessageAt.getTime());
37212
37204
  const start = pagination.page * pagination.pageSize;
37213
37205
  const end = start + pagination.pageSize;
@@ -37259,11 +37251,18 @@ class AXCConversationMockConversationApi extends AXMChatConversationApi {
37259
37251
  await Promise.resolve();
37260
37252
  }
37261
37253
  async markConversationAsRead(conversationId) {
37262
- const conversation = await this.getConversation(conversationId);
37263
- conversation.unreadCount = 0;
37264
- conversationSharedStorage.conversations.set(conversationId, conversation);
37265
- await axConversationIndexedDbStorage.putConversation(conversation);
37266
- conversationSharedStorage.conversationUpdates$.next(conversation);
37254
+ await this.getConversation(conversationId);
37255
+ const messageIds = conversationSharedStorage.messagesByConversation.get(conversationId) ?? [];
37256
+ const marked = await axcMockMarkIncomingMessagesRead(conversationId, messageIds);
37257
+ for (const messageId of marked) {
37258
+ const notificationId = `notif-chat-${messageId}`;
37259
+ try {
37260
+ await this.notificationService.markAsRead({ id: [notificationId] });
37261
+ }
37262
+ catch {
37263
+ // Ignore if no matching notification exists.
37264
+ }
37265
+ }
37267
37266
  }
37268
37267
  async markConversationAsUnread(conversationId) {
37269
37268
  const conversation = await this.getConversation(conversationId);
@@ -37474,12 +37473,25 @@ class AXCConversationMockMessageApi extends AXMChatMessageApi {
37474
37473
  }
37475
37474
  return message;
37476
37475
  }
37476
+ /** Milliseconds since epoch for sorting (IndexedDB may revive timestamps as strings). */
37477
+ #messageTimestampMs(message) {
37478
+ const t = message.timestamp;
37479
+ if (t instanceof Date) {
37480
+ return t.getTime();
37481
+ }
37482
+ if (typeof t === 'string' || typeof t === 'number') {
37483
+ const ms = new Date(t).getTime();
37484
+ return Number.isFinite(ms) ? ms : 0;
37485
+ }
37486
+ return 0;
37487
+ }
37477
37488
  async getMessages(conversationId, pagination) {
37489
+ await awaitConversationMockSharedStorage();
37478
37490
  const messageIds = conversationSharedStorage.messagesByConversation.get(conversationId) || [];
37479
37491
  const allMessages = messageIds
37480
37492
  .map((id) => conversationSharedStorage.messages.get(id))
37481
37493
  .filter((m) => m !== undefined);
37482
- const sorted = allMessages.sort((a, b) => b.timestamp.getTime() - a.timestamp.getTime());
37494
+ const sorted = [...allMessages].sort((a, b) => this.#messageTimestampMs(b) - this.#messageTimestampMs(a));
37483
37495
  const start = pagination.page * pagination.pageSize;
37484
37496
  const end = start + pagination.pageSize;
37485
37497
  return {
@@ -37521,8 +37533,25 @@ class AXCConversationMockMessageApi extends AXMChatMessageApi {
37521
37533
  .filter((m) => m !== undefined);
37522
37534
  const lowerQuery = filters.query.toLowerCase();
37523
37535
  const filtered = allMessages.filter((m) => {
37524
- if ((m.type === 'text' || m.type === 'assist-response') && 'text' in m.payload) {
37525
- return m.payload.text?.toLowerCase().includes(lowerQuery);
37536
+ if (m.type !== 'text' && m.type !== 'assist-response') {
37537
+ return false;
37538
+ }
37539
+ const pl = m.payload;
37540
+ if (pl == null || typeof pl !== 'object' || Array.isArray(pl)) {
37541
+ return false;
37542
+ }
37543
+ const rec = pl;
37544
+ const t = rec['text'];
37545
+ if (typeof t === 'string' && t.toLowerCase().includes(lowerQuery)) {
37546
+ return true;
37547
+ }
37548
+ if (rec['type'] === 'node') {
37549
+ try {
37550
+ return JSON.stringify(rec['content'] ?? '').toLowerCase().includes(lowerQuery);
37551
+ }
37552
+ catch {
37553
+ return false;
37554
+ }
37526
37555
  }
37527
37556
  return false;
37528
37557
  });
@@ -37565,24 +37594,9 @@ class AXCConversationMockMessageApi extends AXMChatMessageApi {
37565
37594
  //#endregion
37566
37595
  //#region ---- Read Receipts ----
37567
37596
  async markAsRead(conversationId, messageIds) {
37568
- for (const messageId of messageIds) {
37569
- const message = conversationSharedStorage.messages.get(messageId);
37570
- if (message && message.status !== 'read') {
37571
- message.status = 'read';
37572
- conversationSharedStorage.messages.set(messageId, message);
37573
- await axConversationIndexedDbStorage.putMessage(message);
37574
- conversationSharedStorage.messageUpdates$.next(message);
37575
- }
37576
- }
37577
- const conversation = conversationSharedStorage.conversations.get(conversationId);
37578
- if (conversation) {
37579
- conversation.unreadCount = Math.max(0, conversation.unreadCount - messageIds.length);
37580
- conversationSharedStorage.conversations.set(conversationId, conversation);
37581
- await axConversationIndexedDbStorage.putConversation(conversation);
37582
- conversationSharedStorage.conversationUpdates$.next(conversation);
37583
- }
37597
+ const marked = await axcMockMarkIncomingMessagesRead(conversationId, messageIds);
37584
37598
  // Keep notification state in sync with message read state.
37585
- await this.markNotificationsAsReadForMessages(messageIds);
37599
+ await this.markNotificationsAsReadForMessages(marked);
37586
37600
  }
37587
37601
  async markAsUnread(conversationId) {
37588
37602
  const conversation = conversationSharedStorage.conversations.get(conversationId);
@@ -37681,16 +37695,36 @@ class AXCConversationMockMessageApi extends AXMChatMessageApi {
37681
37695
  }
37682
37696
  //#endregion
37683
37697
  //#region ---- Message Status ----
37684
- async updateMessageStatus(_messageId, _status) {
37685
- await Promise.resolve();
37698
+ async updateMessageStatus(messageId, status) {
37699
+ const message = conversationSharedStorage.messages.get(messageId);
37700
+ if (!message) {
37701
+ return;
37702
+ }
37703
+ message.status = status;
37704
+ conversationSharedStorage.messages.set(messageId, message);
37705
+ await axConversationIndexedDbStorage.putMessage(message);
37706
+ conversationSharedStorage.messageUpdates$.next(message);
37707
+ await axcMockSyncConversationUnreadCount(message.conversationId);
37686
37708
  }
37687
37709
  async getMessageDeliveryStatus(_messageId) {
37688
37710
  return { delivered: 0, read: 0, total: 0 };
37689
37711
  }
37690
37712
  //#endregion
37691
37713
  //#region ---- Bulk Operations ----
37692
- async markMessagesAsRead(_messageIds) {
37693
- await Promise.resolve();
37714
+ async markMessagesAsRead(messageIds) {
37715
+ const byConversation = new Map();
37716
+ for (const id of messageIds) {
37717
+ const message = conversationSharedStorage.messages.get(id);
37718
+ if (!message) {
37719
+ continue;
37720
+ }
37721
+ const list = byConversation.get(message.conversationId) ?? [];
37722
+ list.push(id);
37723
+ byConversation.set(message.conversationId, list);
37724
+ }
37725
+ for (const [conversationId, ids] of byConversation) {
37726
+ await this.markAsRead(conversationId, ids);
37727
+ }
37694
37728
  }
37695
37729
  async bulkDeleteMessages(_conversationId, _messageIds, _forEveryone) {
37696
37730
  await Promise.resolve();
@@ -37719,13 +37753,10 @@ class AXCConversationMockMessageApi extends AXMChatMessageApi {
37719
37753
  if (conversation) {
37720
37754
  conversation.lastMessageAt = message.timestamp;
37721
37755
  conversation.lastMessage = message;
37722
- const isIncoming = message.senderId !== conversationSharedStorage.currentUserId;
37723
- if (isIncoming) {
37724
- conversation.unreadCount = (conversation.unreadCount ?? 0) + 1;
37725
- }
37726
37756
  conversationSharedStorage.conversations.set(conversation.id, conversation);
37727
37757
  void axConversationIndexedDbStorage.putConversation(conversation);
37728
37758
  conversationSharedStorage.conversationUpdates$.next(conversation);
37759
+ void axcMockSyncConversationUnreadCount(conversationId);
37729
37760
  }
37730
37761
  }
37731
37762
  async createNotificationForIncomingMessage(message) {
@@ -38041,15 +38072,19 @@ class AXCConversationMockMessageApi extends AXMChatMessageApi {
38041
38072
  this.setConversationTyping(conversationId, assistParticipantId, true);
38042
38073
  const placeholderMsg = this.createPlaceholderMessage(conversationId, assistParticipantId, assistId);
38043
38074
  this.publishPlaceholderMessage(placeholderMsg, conversationId);
38075
+ const runStartedAt = Date.now();
38076
+ let lastResolvedModelId;
38044
38077
  try {
38045
38078
  const messages = await this.buildAiMessages(conversationId, assistParticipantId, assistId);
38046
38079
  const modelEntityId = await this.resolveModelEntityId(conversationId, assistId);
38080
+ lastResolvedModelId = modelEntityId;
38047
38081
  if (!modelEntityId) {
38048
38082
  this.finalizeMessage(placeholderMsg, 'No AI model available.', conversationId, [
38049
38083
  axpAiChatTextMessage('assistant', 'No AI model available.'),
38050
- ]);
38084
+ ], { durationMs: Date.now() - runStartedAt });
38051
38085
  return;
38052
38086
  }
38087
+ const modelTitle = await this.resolveModelDisplayTitle(modelEntityId, assistId);
38053
38088
  let streamTextAccumulator = '';
38054
38089
  let streamThinkAccumulator = '';
38055
38090
  /** Context size sent into the engine; `run` appends only new assistant/tool lines after this. */
@@ -38106,13 +38141,23 @@ class AXCConversationMockMessageApi extends AXMChatMessageApi {
38106
38141
  .map((s) => s.trim())
38107
38142
  .filter((s) => s.length > 0)
38108
38143
  .join('\n\n');
38109
- this.finalizeMessage(placeholderMsg, finalContent || streamCombined, conversationId, responseTranscript);
38144
+ this.finalizeMessage(placeholderMsg, finalContent || streamCombined, conversationId, responseTranscript, {
38145
+ usageTotals: runResult.usageTotals,
38146
+ durationMs: Date.now() - runStartedAt,
38147
+ modelEntityId,
38148
+ modelTitle,
38149
+ lastProviderResult: runResult.lastProviderResult,
38150
+ delegatedTranscriptsByCallId: runResult.delegatedTranscriptsByCallId,
38151
+ });
38110
38152
  }
38111
38153
  catch (err) {
38112
38154
  const friendlyError = this.buildUserFriendlyError(err);
38113
38155
  this.finalizeMessage(placeholderMsg, friendlyError, conversationId, [
38114
38156
  axpAiChatTextMessage('assistant', friendlyError),
38115
- ]);
38157
+ ], {
38158
+ durationMs: Date.now() - runStartedAt,
38159
+ modelEntityId: lastResolvedModelId,
38160
+ });
38116
38161
  this.toastService.show({ color: 'danger', title: 'AI Error', content: friendlyError });
38117
38162
  }
38118
38163
  finally {
@@ -38148,7 +38193,7 @@ class AXCConversationMockMessageApi extends AXMChatMessageApi {
38148
38193
  const meta = next.metadata;
38149
38194
  meta['streamDraftText'] = text;
38150
38195
  meta['streamDraftThink'] = think;
38151
- next.payload['text'] = text;
38196
+ next.payload = { type: 'text', text };
38152
38197
  this.rebuildAiTranscriptDraft(next);
38153
38198
  this.emitMessageUpdate(next);
38154
38199
  }
@@ -38342,18 +38387,30 @@ class AXCConversationMockMessageApi extends AXMChatMessageApi {
38342
38387
  }
38343
38388
  else {
38344
38389
  const d = parsed['data'];
38345
- body = {
38346
- success: true,
38347
- data: {
38348
- ...(typeof d?.['answer'] === 'string' ? { answer: d['answer'] } : {}),
38349
- ...(typeof d?.['agentName'] === 'string' ? { agentName: d['agentName'] } : {}),
38350
- ...(typeof d?.['agentId'] === 'string' ? { agentId: d['agentId'] } : {}),
38351
- },
38352
- };
38390
+ const parsedSegs = axpAiParseDelegatedAgentResultSegmentsFromUnknown(d?.['responses']);
38391
+ body =
38392
+ parsedSegs.length > 0
38393
+ ? {
38394
+ success: true,
38395
+ data: {
38396
+ ...(typeof d?.['agentName'] === 'string' ? { agentName: d['agentName'] } : {}),
38397
+ ...(typeof d?.['agentId'] === 'string' ? { agentId: d['agentId'] } : {}),
38398
+ responses: parsedSegs,
38399
+ },
38400
+ }
38401
+ : {
38402
+ success: true,
38403
+ data: {
38404
+ responses: [{ type: 'text', content: typeof tc.output === 'string' ? tc.output : '' }],
38405
+ },
38406
+ };
38353
38407
  }
38354
38408
  }
38355
38409
  catch {
38356
- body = { success: true, data: { answer: tc.output } };
38410
+ body = {
38411
+ success: true,
38412
+ data: { responses: [{ type: 'text', content: tc.output ?? '' }] },
38413
+ };
38357
38414
  }
38358
38415
  lines.push(axpAiChatAgentResultMessage(tc.id, body, tc.name));
38359
38416
  }
@@ -38377,10 +38434,17 @@ class AXCConversationMockMessageApi extends AXMChatMessageApi {
38377
38434
  }
38378
38435
  meta['aiTranscriptDraft'] = lines;
38379
38436
  }
38380
- finalizeMessage(message, text, conversationId, transcript) {
38437
+ finalizeMessage(message, text, conversationId, transcript, runDebug) {
38381
38438
  const base = this.resolveStreamingAssistMessage(message);
38382
38439
  const next = this.snapshotStreamingAssistMessage(base);
38383
- next.payload['text'] = text;
38440
+ const transcriptLines = transcript ?? [];
38441
+ const delivery = axmExtractAssistFinalDeliverableFromTranscript(transcriptLines, text);
38442
+ if (delivery.kind === 'node') {
38443
+ next.payload = { type: 'node', content: delivery.content };
38444
+ }
38445
+ else {
38446
+ next.payload = { type: 'text', text: delivery.text };
38447
+ }
38384
38448
  const meta = next.metadata;
38385
38449
  meta['isStreaming'] = false;
38386
38450
  delete meta['aiTranscriptDraft'];
@@ -38390,6 +38454,40 @@ class AXCConversationMockMessageApi extends AXMChatMessageApi {
38390
38454
  // Full turn trace for assist renderer after reload (IndexedDB + in-memory store).
38391
38455
  meta['aiTranscript'] = transcript;
38392
38456
  }
38457
+ if (runDebug) {
38458
+ if (runDebug.usageTotals) {
38459
+ meta['assistRunUsageTotals'] = runDebug.usageTotals;
38460
+ }
38461
+ else {
38462
+ delete meta['assistRunUsageTotals'];
38463
+ }
38464
+ meta['assistRunDurationMs'] = runDebug.durationMs;
38465
+ if (runDebug.modelEntityId) {
38466
+ meta['assistRunModelEntityId'] = runDebug.modelEntityId;
38467
+ }
38468
+ else {
38469
+ delete meta['assistRunModelEntityId'];
38470
+ }
38471
+ if (runDebug.modelTitle) {
38472
+ meta['assistRunModelTitle'] = runDebug.modelTitle;
38473
+ }
38474
+ else {
38475
+ delete meta['assistRunModelTitle'];
38476
+ }
38477
+ if (runDebug.lastProviderResult) {
38478
+ meta['assistRunLastProviderResult'] = runDebug.lastProviderResult;
38479
+ }
38480
+ else {
38481
+ delete meta['assistRunLastProviderResult'];
38482
+ }
38483
+ if (runDebug.delegatedTranscriptsByCallId &&
38484
+ Object.keys(runDebug.delegatedTranscriptsByCallId).length > 0) {
38485
+ meta['assistRunDelegatedTranscriptsByCallId'] = runDebug.delegatedTranscriptsByCallId;
38486
+ }
38487
+ else {
38488
+ delete meta['assistRunDelegatedTranscriptsByCallId'];
38489
+ }
38490
+ }
38393
38491
  // Retain `toolCalls` (nested tools, specialist stream text) for the conversation UI; not sent to the model.
38394
38492
  this.emitMessageUpdate(next);
38395
38493
  this.updateConversationLastMessage(conversationId, next);
@@ -38406,6 +38504,21 @@ class AXCConversationMockMessageApi extends AXMChatMessageApi {
38406
38504
  * Order: conversation `metadata.modelEntityId` (info bar / overrides), then assist row `modelId`, then first catalog chat model.
38407
38505
  * Empty-assist flow may send before the info bar writes `modelEntityId`, so assist `modelId` must be resolved here.
38408
38506
  */
38507
+ async resolveModelDisplayTitle(modelEntityId, assistId) {
38508
+ try {
38509
+ const models = await this.modelCatalog.listModels({ assistId });
38510
+ const hit = models.find((m) => m.id === modelEntityId);
38511
+ if (!hit) {
38512
+ return modelEntityId;
38513
+ }
38514
+ const title = hit.title?.trim();
38515
+ const name = hit.name?.trim();
38516
+ return title || name || modelEntityId;
38517
+ }
38518
+ catch {
38519
+ return undefined;
38520
+ }
38521
+ }
38409
38522
  async resolveModelEntityId(conversationId, assistId) {
38410
38523
  const conversation = conversationSharedStorage.conversations.get(conversationId);
38411
38524
  const fromMetadata = conversation?.metadata?.['modelEntityId'];
@@ -38481,12 +38594,18 @@ class AXCConversationMockMessageApi extends AXMChatMessageApi {
38481
38594
  return '';
38482
38595
  }
38483
38596
  extractMessageText(message) {
38484
- if ((message.type === 'text' || message.type === 'assist-response') &&
38485
- message.payload &&
38486
- 'text' in message.payload) {
38487
- const text = message.payload.text;
38488
- if (typeof text === 'string')
38489
- return text;
38597
+ if (message.type === 'text' || message.type === 'assist-response') {
38598
+ const pl = message.payload;
38599
+ if (pl != null && typeof pl === 'object' && !Array.isArray(pl)) {
38600
+ const rec = pl;
38601
+ if (rec['type'] === 'node') {
38602
+ return '[Assistant widget]';
38603
+ }
38604
+ const text = rec['text'];
38605
+ if (typeof text === 'string') {
38606
+ return text;
38607
+ }
38608
+ }
38490
38609
  }
38491
38610
  switch (message.type) {
38492
38611
  case 'image':
@@ -38575,6 +38694,279 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
38575
38694
  type: Injectable
38576
38695
  }] });
38577
38696
 
38697
+ //#endregion
38698
+ //#region ---- Helpers ----
38699
+ /** Normalizes message timestamps (IndexedDB may revive as string). */
38700
+ function axcRealtimeMessageTimestamp(message) {
38701
+ const t = message.timestamp;
38702
+ if (t instanceof Date) {
38703
+ return t;
38704
+ }
38705
+ return new Date(t);
38706
+ }
38707
+ function axcRealtimeMessageBelongsToConversation(messageId, conversationId) {
38708
+ const scoped = conversationId?.trim();
38709
+ if (!scoped) {
38710
+ return true;
38711
+ }
38712
+ const message = conversationSharedStorage.messages.get(messageId);
38713
+ return message?.conversationId === scoped;
38714
+ }
38715
+ //#endregion
38716
+ //#region ---- Service ----
38717
+ /**
38718
+ * Mock implementation of AXMChatRealtimeApi using conversation shared storage.
38719
+ * Provides connection management and real-time event subscriptions.
38720
+ */
38721
+ class AXCConversationMockRealtimeApi extends AXMChatRealtimeApi {
38722
+ constructor() {
38723
+ super(...arguments);
38724
+ //#region ---- Connection Status ----
38725
+ this.connectionStatus$ = conversationSharedStorage.connectionStatus$;
38726
+ }
38727
+ //#endregion
38728
+ //#region ---- Connection Management ----
38729
+ async connect(_options) {
38730
+ conversationSharedStorage.connectionStatus$.next('connecting');
38731
+ await conversationSharedStorage.loadFromIndexedDB();
38732
+ conversationSharedStorage.connectionStatus$.next('connected');
38733
+ }
38734
+ async disconnect() {
38735
+ conversationSharedStorage.connectionStatus$.next('disconnected');
38736
+ }
38737
+ isConnected() {
38738
+ return conversationSharedStorage.connectionStatus$.value === 'connected';
38739
+ }
38740
+ async reconnect() {
38741
+ await this.disconnect();
38742
+ await this.connect();
38743
+ }
38744
+ subscribeToConnectionEvents() {
38745
+ return new Observable((subscriber) => {
38746
+ subscriber.next({
38747
+ type: 'connected',
38748
+ timestamp: new Date(),
38749
+ });
38750
+ });
38751
+ }
38752
+ //#endregion
38753
+ //#region ---- Message Events ----
38754
+ subscribeToMessages(conversationId) {
38755
+ return conversationSharedStorage.messageStream$.pipe(filter((msg) => msg.conversationId === conversationId));
38756
+ }
38757
+ subscribeToMessageUpdates(conversationId) {
38758
+ const updates = conversationSharedStorage.messageUpdates$;
38759
+ if (!conversationId) {
38760
+ return updates;
38761
+ }
38762
+ return updates.pipe(filter((msg) => msg.conversationId === conversationId));
38763
+ }
38764
+ subscribeToMessageDeletions(_conversationId) {
38765
+ return conversationSharedStorage.messageDeletions$;
38766
+ }
38767
+ subscribeToMessageReactions(_conversationId) {
38768
+ return conversationSharedStorage.messageUpdates$;
38769
+ }
38770
+ //#endregion
38771
+ //#region ---- Conversation Events ----
38772
+ subscribeToConversationUpdates() {
38773
+ return conversationSharedStorage.conversationUpdates$;
38774
+ }
38775
+ subscribeToConversationCreated() {
38776
+ return new Observable(() => { });
38777
+ }
38778
+ subscribeToConversationDeleted() {
38779
+ return new Observable(() => { });
38780
+ }
38781
+ //#endregion
38782
+ //#region ---- Typing Indicators ----
38783
+ subscribeToTypingIndicators(conversationId) {
38784
+ const scoped = conversationId?.trim();
38785
+ if (!scoped) {
38786
+ return conversationSharedStorage.typingIndicators$;
38787
+ }
38788
+ return conversationSharedStorage.typingIndicators$.pipe(filter((ind) => ind.conversationId === scoped));
38789
+ }
38790
+ //#endregion
38791
+ //#region ---- Presence Updates ----
38792
+ subscribeToPresenceUpdates(_userIds) {
38793
+ return conversationSharedStorage.presenceUpdates$;
38794
+ }
38795
+ //#endregion
38796
+ //#region ---- Read Receipts ----
38797
+ /**
38798
+ * Emits when a message transitions to {@link AXMessage.status} `read` (e.g. mark-as-read / conversation read).
38799
+ * Derived from {@link conversationSharedStorage.messageUpdates$} so mock APIs do not need a separate bus.
38800
+ */
38801
+ subscribeToReadReceipts(conversationId) {
38802
+ const scoped = conversationId?.trim();
38803
+ return conversationSharedStorage.messageUpdates$.pipe(pairwise(), filter(([previous, current]) => current.status === 'read' && (previous.id !== current.id || previous.status !== 'read')), map(([, current]) => ({
38804
+ messageId: current.id,
38805
+ userId: conversationSharedStorage.currentUserId,
38806
+ readAt: new Date(),
38807
+ })), filter((event) => axcRealtimeMessageBelongsToConversation(event.messageId, scoped)));
38808
+ }
38809
+ //#endregion
38810
+ //#region ---- Notifications ----
38811
+ subscribeToNotifications() {
38812
+ return new Observable(() => { });
38813
+ }
38814
+ //#endregion
38815
+ //#region ---- Call Events ----
38816
+ subscribeToCallEvents() {
38817
+ return new Observable(() => { });
38818
+ }
38819
+ //#endregion
38820
+ //#region ---- User Events ----
38821
+ subscribeToUserBlockEvents() {
38822
+ return new Observable(() => { });
38823
+ }
38824
+ subscribeToParticipantEvents(_conversationId) {
38825
+ return new Observable(() => { });
38826
+ }
38827
+ //#endregion
38828
+ //#region ---- System Events ----
38829
+ subscribeToSystemEvents() {
38830
+ return new Observable(() => { });
38831
+ }
38832
+ //#endregion
38833
+ //#region ---- Message Status Events ----
38834
+ /**
38835
+ * New messages emit from {@link conversationSharedStorage.messageStream$}; status transitions emit from
38836
+ * {@link conversationSharedStorage.messageUpdates$} (same message id, different `status`).
38837
+ */
38838
+ subscribeToMessageStatusChanges(conversationId) {
38839
+ const scoped = conversationId?.trim();
38840
+ const fromStream$ = conversationSharedStorage.messageStream$.pipe(map((message) => ({
38841
+ messageId: message.id,
38842
+ status: message.status,
38843
+ timestamp: axcRealtimeMessageTimestamp(message),
38844
+ })), filter((event) => axcRealtimeMessageBelongsToConversation(event.messageId, scoped)));
38845
+ const fromUpdates$ = conversationSharedStorage.messageUpdates$.pipe(pairwise(), filter(([previous, current]) => previous.id === current.id && previous.status !== current.status), map(([, current]) => ({
38846
+ messageId: current.id,
38847
+ status: current.status,
38848
+ timestamp: axcRealtimeMessageTimestamp(current),
38849
+ })), filter((event) => axcRealtimeMessageBelongsToConversation(event.messageId, scoped)));
38850
+ return merge(fromStream$, fromUpdates$);
38851
+ }
38852
+ //#endregion
38853
+ //#region ---- Conversation Settings Events ----
38854
+ subscribeToConversationSettingsChanges(_conversationId) {
38855
+ return new Observable(() => { });
38856
+ }
38857
+ //#endregion
38858
+ //#region ---- Draft Events ----
38859
+ subscribeToDraftChanges(_conversationId) {
38860
+ return new Observable(() => { });
38861
+ }
38862
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXCConversationMockRealtimeApi, deps: null, target: i0.ɵɵFactoryTarget.Injectable }); }
38863
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXCConversationMockRealtimeApi }); }
38864
+ }
38865
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXCConversationMockRealtimeApi, decorators: [{
38866
+ type: Injectable
38867
+ }] });
38868
+
38869
+ //#endregion
38870
+ //#region ---- Service ----
38871
+ /**
38872
+ * Mock implementation of AXMChatUserApi using conversation shared storage.
38873
+ * Provides user profile, discovery, presence, blocking, and settings operations.
38874
+ */
38875
+ class AXCConversationMockUserApi extends AXMChatUserApi {
38876
+ //#region ---- User Profile ----
38877
+ async getCurrentUser() {
38878
+ const user = conversationSharedStorage.participants.get(conversationSharedStorage.currentUserId);
38879
+ if (!user) {
38880
+ throw this.createError('USER_NOT_FOUND', 'Current user not found', 404);
38881
+ }
38882
+ return user;
38883
+ }
38884
+ async updateProfile(updates) {
38885
+ const user = await this.getCurrentUser();
38886
+ return { ...user, ...updates };
38887
+ }
38888
+ async uploadAvatar(file) {
38889
+ return new Promise((resolve) => {
38890
+ const reader = new FileReader();
38891
+ reader.onloadend = () => resolve(reader.result);
38892
+ reader.readAsDataURL(file);
38893
+ });
38894
+ }
38895
+ //#endregion
38896
+ //#region ---- User Discovery ----
38897
+ async getUsers(filters) {
38898
+ const users = Array.from(conversationSharedStorage.participants.values());
38899
+ const filtered = users.filter((u) => u.id !== conversationSharedStorage.currentUserId && !axmIsAssistPeerParticipant(u));
38900
+ if (!filters?.query)
38901
+ return filtered;
38902
+ const q = filters.query.toLowerCase();
38903
+ ``;
38904
+ return filtered.filter((u) => {
38905
+ const name = u.name.toLowerCase();
38906
+ const desc = (u.description ?? '').toLowerCase();
38907
+ return name.includes(q) || desc.includes(q);
38908
+ });
38909
+ }
38910
+ async searchUsers(query) {
38911
+ return this.getUsers({ query });
38912
+ }
38913
+ async getUserById(userId) {
38914
+ const user = conversationSharedStorage.participants.get(userId);
38915
+ if (!user) {
38916
+ throw this.createError('USER_NOT_FOUND', `User ${userId} not found`, 404);
38917
+ }
38918
+ return user;
38919
+ }
38920
+ async getUsersByIds(userIds) {
38921
+ return userIds
38922
+ .map((id) => conversationSharedStorage.participants.get(id))
38923
+ .filter((u) => u !== undefined);
38924
+ }
38925
+ //#endregion
38926
+ //#region ---- Presence Management ----
38927
+ async getUserPresence(userId) {
38928
+ return {
38929
+ userId,
38930
+ status: 'online',
38931
+ lastSeen: new Date(),
38932
+ };
38933
+ }
38934
+ async updatePresence(_status, _statusText) {
38935
+ await Promise.resolve();
38936
+ }
38937
+ //#endregion
38938
+ //#region ---- User Blocking & Reporting ----
38939
+ async blockUser(_userId, _reason) {
38940
+ await Promise.resolve();
38941
+ }
38942
+ async unblockUser(_userId) {
38943
+ await Promise.resolve();
38944
+ }
38945
+ async getBlockedUsers() {
38946
+ return [];
38947
+ }
38948
+ async reportUser(_userId, _reason) {
38949
+ await Promise.resolve();
38950
+ }
38951
+ //#endregion
38952
+ //#region ---- User Settings & Preferences ----
38953
+ async getUserSettings() {
38954
+ return {
38955
+ theme: 'light',
38956
+ language: 'en',
38957
+ notifications: true,
38958
+ };
38959
+ }
38960
+ async updateUserSettings(_settings) {
38961
+ await Promise.resolve();
38962
+ }
38963
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXCConversationMockUserApi, deps: null, target: i0.ɵɵFactoryTarget.Injectable }); }
38964
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXCConversationMockUserApi }); }
38965
+ }
38966
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXCConversationMockUserApi, decorators: [{
38967
+ type: Injectable
38968
+ }] });
38969
+
38578
38970
  //#region ---- Imports ----
38579
38971
  //#endregion
38580
38972
  //#region ---- Helpers ----
@@ -61618,7 +62010,7 @@ class AXCSecurityManagementMockModule {
61618
62010
  provideQuerySetups([
61619
62011
  {
61620
62012
  key: 'SecurityManagement:User:RolesForListColumn',
61621
- loader: () => import('./acorex-connectivity-mock-user-roles-for-list-column.query-BSN7vEKz.mjs').then((m) => m.UserRolesForListColumnQuery),
62013
+ loader: () => import('./acorex-connectivity-mock-user-roles-for-list-column.query-DBhWkX3w.mjs').then((m) => m.UserRolesForListColumnQuery),
61622
62014
  },
61623
62015
  ]),
61624
62016
  ] }); }
@@ -61662,7 +62054,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
61662
62054
  provideQuerySetups([
61663
62055
  {
61664
62056
  key: 'SecurityManagement:User:RolesForListColumn',
61665
- loader: () => import('./acorex-connectivity-mock-user-roles-for-list-column.query-BSN7vEKz.mjs').then((m) => m.UserRolesForListColumnQuery),
62057
+ loader: () => import('./acorex-connectivity-mock-user-roles-for-list-column.query-DBhWkX3w.mjs').then((m) => m.UserRolesForListColumnQuery),
61666
62058
  },
61667
62059
  ]),
61668
62060
  ],
@@ -71387,7 +71779,7 @@ class AXCWorkflowManagementMockModule {
71387
71779
  provideCommandSetups([
71388
71780
  {
71389
71781
  key: 'workflow-activity:assign-to-manager',
71390
- command: () => import('./acorex-connectivity-mock-assign-to-manager.activity-DQRHQ_jG.mjs').then((c) => c.AssignToManagerActivity),
71782
+ command: () => import('./acorex-connectivity-mock-assign-to-manager.activity-BgaXGmcT.mjs').then((c) => c.AssignToManagerActivity),
71391
71783
  },
71392
71784
  {
71393
71785
  key: 'workflow-activity:get-current-user-manager',
@@ -71498,7 +71890,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
71498
71890
  provideCommandSetups([
71499
71891
  {
71500
71892
  key: 'workflow-activity:assign-to-manager',
71501
- command: () => import('./acorex-connectivity-mock-assign-to-manager.activity-DQRHQ_jG.mjs').then((c) => c.AssignToManagerActivity),
71893
+ command: () => import('./acorex-connectivity-mock-assign-to-manager.activity-BgaXGmcT.mjs').then((c) => c.AssignToManagerActivity),
71502
71894
  },
71503
71895
  {
71504
71896
  key: 'workflow-activity:get-current-user-manager',
@@ -75951,5 +76343,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
75951
76343
  * Generated bundle index. Do not edit.
75952
76344
  */
75953
76345
 
75954
- export { AXCFinancialCoreMockModule as $, AXCAiChatRouterService as A, AXCCalendarDataSeeder as B, AXCCalendarEventDataSeeder as C, AXCCalendarManagementMockModule as D, AXCCommandRegistryDataSeeder as E, AXCCommonMockModule as F, AXCContactCoreMockModule as G, AXCContentManagementMockModule as H, AXCConversationDataSeeder as I, AXCConversationMockConversationApi as J, AXCConversationMockMessageApi as K, AXCConversationMockModule as L, AXCConversationMockRealtimeApi as M, AXCConversationMockUserApi as N, AXCCustomerManagementMockModule as O, AXCDashboardManagementMockModule as P, AXCDataManagementMockModule as Q, AXCDexieEntityStorageService as R, AXCDocumentManagementMockModule as S, AXCEditionDataSeeder as T, AXCEntityDefinitionSeederService as U, AXCEntityDefinitionsModule as V, AXCEntityStorageInsertCommand as W, AXCEntityStorageModule as X, AXCEntityStorageQueryQuery as Y, AXCFileStorageServiceDexie as Z, AXCFileStorageServiceFirestore as _, AXMAiModelStableIds as a, AXMEmploymentTypeDataSeeder as a$, AXCFirestoreEntityStorageService as a0, AXCFormTemplateManagementMockModule as a1, AXCGoogleStrategyMock as a2, AXCHealthCoreMockModule as a3, AXCHelpDeskMockModule as a4, AXCHumanCapitalManagementMockModule as a5, AXCIdentifierManagementMockModule as a6, AXCImageCaptchaChallengeProviderMock as a7, AXCLearningManagementMockModule as a8, AXCLocaleManagementMockModule as a9, AXCTenantManagementMockModule as aA, AXCTenantSeeder as aB, AXCTextTemplateRenderBackend as aC, AXCTokensDataSeeder as aD, AXCUserPassStrategyMock as aE, AXCVersionDB as aF, AXCVersioningService as aG, AXCWidgetCatalogDataSeeder as aH, AXCWorkflowCategorySeeder as aI, AXCWorkflowDefinitionDataSeeder as aJ, AXCWorkflowEngine as aK, AXCWorkflowExecutionDB as aL, AXCWorkflowExecutionStoreDexie as aM, AXCWorkflowExecutionStoreFirestore as aN, AXCWorkflowInstanceCartableDemoSeeder as aO, AXCWorkflowManagementMockModule as aP, AXC_ENTITY_STORAGE_BACKEND_TYPE as aQ, AXC_FIRESTORE_CONFIG as aR, AXC_FIRESTORE_DB as aS, AXC_WORKFLOW_EXECUTION_STORE as aT, AXMAiDemisDefaultAssistId as aU, AXMAiPlatformDefaultAssistId as aV, AXMAutomationDataSeeder as aW, AXMBusinessUnitDataSeeder as aX, AXMCalendarEventTypeSeeder as aY, AXMDashboardChartDataSourceDefinition as aZ, AXMEmployeeDataSeeder as a_, AXCLocationManagementMockModule as aa, AXCLockService as ab, AXCMeasurementCoreMockModule as ac, AXCMeetingManagementMockModule as ad, AXCMetaDataDefinitionDataSeeder as ae, AXCMetadataCategorySeeder as af, AXCMiddlewaresModule as ag, AXCMockCaptchaChallengeComponent as ah, AXCMockEntityLogListener as ai, AXCMockModule as aj, AXCMockShowMetaDataFormPopupCommand as ak, AXCNotificationManagementMockModule as al, AXCOrderManagementMockModule as am, AXCOrganizationManagementMockModule as an, AXCPersonCoreMockModule as ao, AXCPlatformManagementMockModule as ap, AXCProcurementManagementMockModule as aq, AXCProductCatalogMockModule as ar, AXCProjectManagementMockModule as as, AXCQueryRegistryDataSeeder as at, AXCReportManagementMockModule as au, AXCSecurityManagementMockModule as av, AXCStoredEntityDefinitionLoader as aw, AXCSubscriptionManagementMockModule as ax, AXCSupplierManagementMockModule as ay, AXCTaskManagementMockModule as az, resolveDelegatedAssistOptionString as b, HW as b$, AXMFormDataSourcesProvider as b0, AXMJobDefinitionDataSeeder as b1, AXMJobLevelDataSeeder as b2, AXMLeaveRequestDataSeeder as b3, AXMMeetingDataSeeder as b4, AXMMeetingFilesDataSeeder as b5, AXMMeetingParticipantDataSeeder as b6, AXMMeetingRoleTypeDataSeeder as b7, AXMMeetingSessionDataSeeder as b8, AXMMeetingTypeDataSeeder as b9, AXPMockSequenceProvider as bA, AXPRoomDataSeeder as bB, AXPSecurityManagementRoleDataSeeder as bC, AXPSecurityManagementUserDataSeeder as bD, AXPTaskBoardPlatformManagementTaskProvider as bE, AXPTaskBoardProjectManagementTaskProvider as bF, AXVChangeType as bG, BCC as bH, BOC as bI, BUSINESS_UNITS_MOCK as bJ, CHAT_LAST_MESSAGE_IDS as bK, COSTMANAGER_ENTERPRISE as bL, COSTMANAGER_PROFESSIONAL as bM, COSTMANAGER_STANDARD as bN, CP as bO, CRM_ENTERPRISE as bP, DASHBOARDS as bQ, EDITIONS as bR, EMPLOYEES_MOCK as bS, EMPLOYMENT_TYPES_MOCK as bT, ENTITY_DEFINITION_MAP as bU, ENTITY_REGISTRY as bV, FINANCE_BASIC as bW, FINANCE_ENTERPRISE as bX, FINANCE_PRO as bY, G as bZ, HR_ENTERPRISE as b_, AXMMeetingTypeFileTemplateDataSeeder as ba, AXMPositionAssignmentDataSeeder as bb, AXMPositionDataSeeder as bc, AXMQuestionBankItemCategoryDataSeeder as bd, AXMQuestionBankItemDataSeeder as be, AXMQuestionnaireCalculationDataSeeder as bf, AXMQuestionnaireCategoryDataSeeder as bg, AXMQuestionnaireDataSeeder as bh, AXMResponsibilityDataSeeder as bi, AXMTagDataSeeder as bj, AXMTeamBusinessUnitDataSeeder as bk, AXMTeamDataSeeder as bl, AXMTeamMemberDataSeeder as bm, AXMTeamMemberRoleDataSeeder as bn, AXMWorkflowDashboardChartDataSourceDefinition as bo, AXM_AI_REGISTRY_COMMAND_NAME as bp, AXM_AI_REGISTRY_QUERY_NAME as bq, AXM_CORPORATE_BUSINESS_UNIT_ID as br, AXPDashboardDataSeeder as bs, AXPIdentifierDB as bt, AXPMessageDataSeeder as bu, AXPMockChecksumProvider as bv, AXPMockClockProvider as bw, AXPMockIdentifierService as bx, AXPMockLookupProvider as by, AXPMockPolicyProvider as bz, axcSyncSingleEmployeeDenormalizedOrgFields as c, axVersionDB as c$, JOB_DEFINITIONS_CATEGORY_MOCK as c0, JOB_DEFINITIONS_MOCK as c1, JOB_DEFINITION_CATEGORY_KEY_TO_ID as c2, JOB_LEVELS_MOCK as c3, LASER_PLUMBING_TENANT_ID as c4, LEAVE_REQUESTS_MOCK as c5, METADATA_CATEGORY_IDS as c6, METADATA_GENERAL_CATEGORY_REFS as c7, METADATA_SYSTEM_CATEGORY_REFS as c8, MLC as c9, SHOP_BASIC as cA, SHOP_ENTERPRISE as cB, SHOP_PRO as cC, TAGS_MOCK as cD, TASKS as cE, TASK_STATUSES as cF, TASK_TEMPLATES as cG, TASK_TYPES as cH, TEAMS_CATEGORY_MOCK as cI, TEAMS_MOCK as cJ, TEAM_BUSINESS_UNITS_MOCK as cK, TEAM_CATEGORY_KEY_TO_ID as cL, TEAM_MEMBERS_MOCK as cM, TEAM_MEMBER_ROLES_MOCK as cN, TIMEPLICITY_TENANT_ID as cO, TLA as cP, TOKENS as cQ, TPC as cR, VISIBILITY_FILTER_BYPASS as cS, WORKFLOW_CATEGORIES as cT, WS as cU, activityCategoryMocks as cV, activityDefinitionEntityMock as cW, applyEntityDefinitionFirestoreSnapshot as cX, automationCommandMiddleware as cY, automationMock as cZ, avatarInterface as c_, OHR as ca, ORDERING_BASIC as cb, ORDERING_ENTERPRISE as cc, ORDERING_STANDARD as cd, OWNERSHIP_FILTER_BYPASS as ce, PLATFORM_CONSOLE as cf, PLATFORM_TENANT_ID as cg, PM as ch, POSITIONS_CATEGORY_MOCK as ci, POSITIONS_MOCK as cj, POSITION_ASSIGNMENTS_MOCK as ck, QCP as cl, QGEN as cm, QHW as cn, QOHR as co, QPM as cp, QTLE as cq, QUESTIONNAIRE_CATEGORY_MOCK as cr, QUESTION_BANK_ITEM_CATEGORY_MOCK as cs, QWS as ct, RESPONSIBILITIES_CATEGORY_MOCK as cu, RESPONSIBILITIES_MOCK as cv, RESPONSIBILITY_CATEGORY_KEY_TO_ID as cw, SAFETYMINDER_BASIC as cx, SAFETYMINDER_ENTERPRISE as cy, SAFETYMINDER_PROFESSIONAL as cz, ACTIVITY_CATEGORIES as d, mockParticipantIndexForSecurityUserId as d$, axWorkflowExecutionDB as d0, axcPatchEmployeeActivePrimaryBusinessUnitRefsFromRows as d1, axcPatchEmployeeActivePrimaryPositionRefsFromRows as d2, axcPatchEmployeeManagerRefsFromRows as d3, axcResolveCommandRegistrySeedId as d4, axcResolveQueryRegistrySeedId as d5, axcResolveWidgetCatalogSeedId as d6, bankCategory as d7, buildEntityStorageQuickSearchFilter as d8, buildWorkflowInstanceCartableDemoRows as d9, fileUploaderInterface as dA, finalizeActivityCategoryItemCounts as dB, findEmployeeById as dC, folderStorageMiddleware as dD, groupOrderItemCalculatorMiddleware as dE, historyMiddleware as dF, identifierCommitMiddleware as dG, imageInterface as dH, inspectionOkXNaInterface as dI, loadMockPropertyDefinitions as dJ, lockGuardMiddleware as dK, longTextAnswerInterface as dL, lookupInterface as dM, lookupResolverMiddleware as dN, mapInterface as dO, meetingFilesMock as dP, meetingIds as dQ, meetingMock as dR, meetingParticipantMock as dS, meetingRoleTypeMock as dT, meetingSessionMock as dU, meetingTimeSlotMock as dV, meetingTypeFileTemplateMock as dW, meetingTypeMock as dX, mergeDetailRelationMiddleware as dY, mergeQuickSearchIntoRequest as dZ, metadataCategoryMocks as d_, bypassAllFilters as da, bypassOwnershipFilter as db, bypassVisibilityFilter as dc, calendarEventMock as dd, calendarEventTypeMockData as de, calendarMock as df, chatMessageMock as dg, chatMock as dh, checkboxInterface as di, childCountMiddleware as dj, clearEntityDefinitionFirestoreCollections as dk, collectQuickSearchFieldPathsFromEntityDefinition as dl, colorInterface as dm, computeDiff as dn, contactInterface as dp, conversationDemoSeedUserIds as dq, createFileCastMiddleware as dr, createWidgetLayoutConfig as ds, dateInterface as dt, dateTimeInterface as du, descriptionInterface as dv, documentFolderSyncMiddleware as dw, emailInterface as dx, entityDefDb as dy, entityValidationMiddleware as dz, ACTIVITY_CATEGORY_ID_BY_KEY as e, mockQuestionBankItemByName as e0, mockRoleDefinitions as e1, multipleChoiceInterface as e2, multipleSelectInterface as e3, normalizeAnyFileArrayForView as e4, normalizeSnapshotFileFieldsForView as e5, numberInterface as e6, parseEntityStorageInsertData as e7, parseEntityStorageQueryRequest as e8, participantIds as e9, textInterface as eA, timeDurationInterface as eB, titleInterface as eC, toUiRows as eD, toggleInterface as eE, tokenCategoryIds as eF, tokenCategoryMocks as eG, urlInterface as eH, versionInterface as eI, visibilityFilterMiddleware as eJ, workflowDefinitionEntityMock as eK, workflowDefinitionIds as eL, workflowDefinitionMock as eM, yesNoInterface as eN, participantMock as ea, passwordInterface as eb, personIdentifierTypeMock as ec, personIds as ed, personLegalIds as ee, personMock as ef, personNaturalIds as eg, phoneInterface as eh, primaryMiddleware as ei, provideMockPropertySetups as ej, qrcodeInterface as ek, questionBankItemMock as el, questionnaireCalculationMock as em, questionnaireMock as en, ratingInterface as eo, richTextInterface as ep, scaleInterface as eq, selectInterface as er, selectionListInterface as es, sexAtBirthInterface as et, signatureInterface as eu, signatureLoaderMiddleware as ev, statusDefaultMiddleware as ew, tagInterface as ex, tenantMocks as ey, textAreaInterface as ez, ACTIVITY_DEFINITIONS as f, AI_ASSIST_MOCK as g, AI_MODEL_MOCK as h, APPLICATIONS as i, APPLICATION_CATEGORY_IDS as j, APPLICATION_CATEGORY_MOCKS as k, AXCActivityCategorySeeder as l, mockUsers as m, AXCActivityDefinitionSeeder as n, AXCAiAssistSeeder as o, AXCAiManagementMockModule as p, AXCAiModelSeeder as q, resolveDelegatedAssistOptionModel as r, AXCAppTermDataSeeder as s, AXCAppVersionDataSeeder as t, AXCApplicationCategoryDataSeeder as u, AXCApplicationDataSeeder as v, AXCApplicationManagementMockModule as w, AXCAssessmentManagementMockModule as x, AXCAssetManagementMockModule as y, AXCAuthMockModule as z };
75955
- //# sourceMappingURL=acorex-connectivity-mock-acorex-connectivity-mock-BvDCXP5M.mjs.map
76346
+ export { AXCFinancialCoreMockModule as $, AXCAiChatRouterService as A, AXCCalendarDataSeeder as B, AXCCalendarEventDataSeeder as C, AXCCalendarManagementMockModule as D, AXCCommandRegistryDataSeeder as E, AXCCommonMockModule as F, AXCContactCoreMockModule as G, AXCContentManagementMockModule as H, AXCConversationDataSeeder as I, AXCConversationMockConversationApi as J, AXCConversationMockMessageApi as K, AXCConversationMockModule as L, AXCConversationMockRealtimeApi as M, AXCConversationMockUserApi as N, AXCCustomerManagementMockModule as O, AXCDashboardManagementMockModule as P, AXCDataManagementMockModule as Q, AXCDexieEntityStorageService as R, AXCDocumentManagementMockModule as S, AXCEditionDataSeeder as T, AXCEntityDefinitionSeederService as U, AXCEntityDefinitionsModule as V, AXCEntityStorageInsertCommand as W, AXCEntityStorageModule as X, AXCEntityStorageQueryQuery as Y, AXCFileStorageServiceDexie as Z, AXCFileStorageServiceFirestore as _, AXMAiModelStableIds as a, AXMEmploymentTypeDataSeeder as a$, AXCFirestoreEntityStorageService as a0, AXCFormTemplateManagementMockModule as a1, AXCGoogleStrategyMock as a2, AXCHealthCoreMockModule as a3, AXCHelpDeskMockModule as a4, AXCHumanCapitalManagementMockModule as a5, AXCIdentifierManagementMockModule as a6, AXCImageCaptchaChallengeProviderMock as a7, AXCLearningManagementMockModule as a8, AXCLocaleManagementMockModule as a9, AXCTenantManagementMockModule as aA, AXCTenantSeeder as aB, AXCTextTemplateRenderBackend as aC, AXCTokensDataSeeder as aD, AXCUserPassStrategyMock as aE, AXCVersionDB as aF, AXCVersioningService as aG, AXCWidgetCatalogDataSeeder as aH, AXCWorkflowCategorySeeder as aI, AXCWorkflowDefinitionDataSeeder as aJ, AXCWorkflowEngine as aK, AXCWorkflowExecutionDB as aL, AXCWorkflowExecutionStoreDexie as aM, AXCWorkflowExecutionStoreFirestore as aN, AXCWorkflowInstanceCartableDemoSeeder as aO, AXCWorkflowManagementMockModule as aP, AXC_ENTITY_STORAGE_BACKEND_TYPE as aQ, AXC_FIRESTORE_CONFIG as aR, AXC_FIRESTORE_DB as aS, AXC_WORKFLOW_EXECUTION_STORE as aT, AXMAiDemisAssistantAssistId as aU, AXMAiPlatformAssistantAssistId as aV, AXMAutomationDataSeeder as aW, AXMBusinessUnitDataSeeder as aX, AXMCalendarEventTypeSeeder as aY, AXMDashboardChartDataSourceDefinition as aZ, AXMEmployeeDataSeeder as a_, AXCLocationManagementMockModule as aa, AXCLockService as ab, AXCMeasurementCoreMockModule as ac, AXCMeetingManagementMockModule as ad, AXCMetaDataDefinitionDataSeeder as ae, AXCMetadataCategorySeeder as af, AXCMiddlewaresModule as ag, AXCMockCaptchaChallengeComponent as ah, AXCMockEntityLogListener as ai, AXCMockModule as aj, AXCMockShowMetaDataFormPopupCommand as ak, AXCNotificationManagementMockModule as al, AXCOrderManagementMockModule as am, AXCOrganizationManagementMockModule as an, AXCPersonCoreMockModule as ao, AXCPlatformManagementMockModule as ap, AXCProcurementManagementMockModule as aq, AXCProductCatalogMockModule as ar, AXCProjectManagementMockModule as as, AXCQueryRegistryDataSeeder as at, AXCReportManagementMockModule as au, AXCSecurityManagementMockModule as av, AXCStoredEntityDefinitionLoader as aw, AXCSubscriptionManagementMockModule as ax, AXCSupplierManagementMockModule as ay, AXCTaskManagementMockModule as az, resolveDelegatedAssistOptionString as b, HW as b$, AXMFormDataSourcesProvider as b0, AXMJobDefinitionDataSeeder as b1, AXMJobLevelDataSeeder as b2, AXMLeaveRequestDataSeeder as b3, AXMMeetingDataSeeder as b4, AXMMeetingFilesDataSeeder as b5, AXMMeetingParticipantDataSeeder as b6, AXMMeetingRoleTypeDataSeeder as b7, AXMMeetingSessionDataSeeder as b8, AXMMeetingTypeDataSeeder as b9, AXPMockSequenceProvider as bA, AXPRoomDataSeeder as bB, AXPSecurityManagementRoleDataSeeder as bC, AXPSecurityManagementUserDataSeeder as bD, AXPTaskBoardPlatformManagementTaskProvider as bE, AXPTaskBoardProjectManagementTaskProvider as bF, AXVChangeType as bG, BCC as bH, BOC as bI, BUSINESS_UNITS_MOCK as bJ, CHAT_LAST_MESSAGE_IDS as bK, COSTMANAGER_ENTERPRISE as bL, COSTMANAGER_PROFESSIONAL as bM, COSTMANAGER_STANDARD as bN, CP as bO, CRM_ENTERPRISE as bP, DASHBOARDS as bQ, EDITIONS as bR, EMPLOYEES_MOCK as bS, EMPLOYMENT_TYPES_MOCK as bT, ENTITY_DEFINITION_MAP as bU, ENTITY_REGISTRY as bV, FINANCE_BASIC as bW, FINANCE_ENTERPRISE as bX, FINANCE_PRO as bY, G as bZ, HR_ENTERPRISE as b_, AXMMeetingTypeFileTemplateDataSeeder as ba, AXMPositionAssignmentDataSeeder as bb, AXMPositionDataSeeder as bc, AXMQuestionBankItemCategoryDataSeeder as bd, AXMQuestionBankItemDataSeeder as be, AXMQuestionnaireCalculationDataSeeder as bf, AXMQuestionnaireCategoryDataSeeder as bg, AXMQuestionnaireDataSeeder as bh, AXMResponsibilityDataSeeder as bi, AXMTagDataSeeder as bj, AXMTeamBusinessUnitDataSeeder as bk, AXMTeamDataSeeder as bl, AXMTeamMemberDataSeeder as bm, AXMTeamMemberRoleDataSeeder as bn, AXMWorkflowDashboardChartDataSourceDefinition as bo, AXM_AI_REGISTRY_COMMAND_NAME as bp, AXM_AI_REGISTRY_QUERY_NAME as bq, AXM_CORPORATE_BUSINESS_UNIT_ID as br, AXPDashboardDataSeeder as bs, AXPIdentifierDB as bt, AXPMessageDataSeeder as bu, AXPMockChecksumProvider as bv, AXPMockClockProvider as bw, AXPMockIdentifierService as bx, AXPMockLookupProvider as by, AXPMockPolicyProvider as bz, axcSyncSingleEmployeeDenormalizedOrgFields as c, awaitConversationMockSharedStorage as c$, JOB_DEFINITIONS_CATEGORY_MOCK as c0, JOB_DEFINITIONS_MOCK as c1, JOB_DEFINITION_CATEGORY_KEY_TO_ID as c2, JOB_LEVELS_MOCK as c3, LASER_PLUMBING_TENANT_ID as c4, LEAVE_REQUESTS_MOCK as c5, METADATA_CATEGORY_IDS as c6, METADATA_GENERAL_CATEGORY_REFS as c7, METADATA_SYSTEM_CATEGORY_REFS as c8, MLC as c9, SHOP_BASIC as cA, SHOP_ENTERPRISE as cB, SHOP_PRO as cC, TAGS_MOCK as cD, TASKS as cE, TASK_STATUSES as cF, TASK_TEMPLATES as cG, TASK_TYPES as cH, TEAMS_CATEGORY_MOCK as cI, TEAMS_MOCK as cJ, TEAM_BUSINESS_UNITS_MOCK as cK, TEAM_CATEGORY_KEY_TO_ID as cL, TEAM_MEMBERS_MOCK as cM, TEAM_MEMBER_ROLES_MOCK as cN, TIMEPLICITY_TENANT_ID as cO, TLA as cP, TOKENS as cQ, TPC as cR, VISIBILITY_FILTER_BYPASS as cS, WORKFLOW_CATEGORIES as cT, WS as cU, activityCategoryMocks as cV, activityDefinitionEntityMock as cW, applyEntityDefinitionFirestoreSnapshot as cX, automationCommandMiddleware as cY, automationMock as cZ, avatarInterface as c_, OHR as ca, ORDERING_BASIC as cb, ORDERING_ENTERPRISE as cc, ORDERING_STANDARD as cd, OWNERSHIP_FILTER_BYPASS as ce, PLATFORM_CONSOLE as cf, PLATFORM_TENANT_ID as cg, PM as ch, POSITIONS_CATEGORY_MOCK as ci, POSITIONS_MOCK as cj, POSITION_ASSIGNMENTS_MOCK as ck, QCP as cl, QGEN as cm, QHW as cn, QOHR as co, QPM as cp, QTLE as cq, QUESTIONNAIRE_CATEGORY_MOCK as cr, QUESTION_BANK_ITEM_CATEGORY_MOCK as cs, QWS as ct, RESPONSIBILITIES_CATEGORY_MOCK as cu, RESPONSIBILITIES_MOCK as cv, RESPONSIBILITY_CATEGORY_KEY_TO_ID as cw, SAFETYMINDER_BASIC as cx, SAFETYMINDER_ENTERPRISE as cy, SAFETYMINDER_PROFESSIONAL as cz, ACTIVITY_CATEGORIES as d, mockParticipantIndexForSecurityUserId as d$, axVersionDB as d0, axWorkflowExecutionDB as d1, axcPatchEmployeeActivePrimaryBusinessUnitRefsFromRows as d2, axcPatchEmployeeActivePrimaryPositionRefsFromRows as d3, axcPatchEmployeeManagerRefsFromRows as d4, axcResolveCommandRegistrySeedId as d5, axcResolveQueryRegistrySeedId as d6, axcResolveWidgetCatalogSeedId as d7, bankCategory as d8, buildEntityStorageQuickSearchFilter as d9, fileUploaderInterface as dA, finalizeActivityCategoryItemCounts as dB, findEmployeeById as dC, folderStorageMiddleware as dD, groupOrderItemCalculatorMiddleware as dE, historyMiddleware as dF, identifierCommitMiddleware as dG, imageInterface as dH, inspectionOkXNaInterface as dI, loadMockPropertyDefinitions as dJ, lockGuardMiddleware as dK, longTextAnswerInterface as dL, lookupInterface as dM, lookupResolverMiddleware as dN, mapInterface as dO, meetingFilesMock as dP, meetingIds as dQ, meetingMock as dR, meetingParticipantMock as dS, meetingRoleTypeMock as dT, meetingSessionMock as dU, meetingTimeSlotMock as dV, meetingTypeFileTemplateMock as dW, meetingTypeMock as dX, mergeDetailRelationMiddleware as dY, mergeQuickSearchIntoRequest as dZ, metadataCategoryMocks as d_, buildWorkflowInstanceCartableDemoRows as da, bypassAllFilters as db, bypassOwnershipFilter as dc, bypassVisibilityFilter as dd, calendarEventMock as de, calendarEventTypeMockData as df, calendarMock as dg, chatMessageMock as dh, chatMock as di, checkboxInterface as dj, childCountMiddleware as dk, clearEntityDefinitionFirestoreCollections as dl, colorInterface as dm, computeDiff as dn, contactInterface as dp, conversationDemoSeedUserIds as dq, createFileCastMiddleware as dr, createWidgetLayoutConfig as ds, dateInterface as dt, dateTimeInterface as du, descriptionInterface as dv, documentFolderSyncMiddleware as dw, emailInterface as dx, entityDefDb as dy, entityValidationMiddleware as dz, ACTIVITY_CATEGORY_ID_BY_KEY as e, mockQuestionBankItemByName as e0, mockRoleDefinitions as e1, multipleChoiceInterface as e2, multipleSelectInterface as e3, normalizeAnyFileArrayForView as e4, normalizeSnapshotFileFieldsForView as e5, numberInterface as e6, parseEntityStorageInsertData as e7, parseEntityStorageQueryRequest as e8, participantIds as e9, textInterface as eA, timeDurationInterface as eB, titleInterface as eC, toUiRows as eD, toggleInterface as eE, tokenCategoryIds as eF, tokenCategoryMocks as eG, urlInterface as eH, versionInterface as eI, visibilityFilterMiddleware as eJ, workflowDefinitionEntityMock as eK, workflowDefinitionIds as eL, workflowDefinitionMock as eM, yesNoInterface as eN, participantMock as ea, passwordInterface as eb, personIdentifierTypeMock as ec, personIds as ed, personLegalIds as ee, personMock as ef, personNaturalIds as eg, phoneInterface as eh, primaryMiddleware as ei, provideMockPropertySetups as ej, qrcodeInterface as ek, questionBankItemMock as el, questionnaireCalculationMock as em, questionnaireMock as en, ratingInterface as eo, richTextInterface as ep, scaleInterface as eq, selectInterface as er, selectionListInterface as es, sexAtBirthInterface as et, signatureInterface as eu, signatureLoaderMiddleware as ev, statusDefaultMiddleware as ew, tagInterface as ex, tenantMocks as ey, textAreaInterface as ez, ACTIVITY_DEFINITIONS as f, AI_ASSIST_MOCK as g, AI_MODEL_MOCK as h, APPLICATIONS as i, APPLICATION_CATEGORY_IDS as j, APPLICATION_CATEGORY_MOCKS as k, AXCActivityCategorySeeder as l, mockUsers as m, AXCActivityDefinitionSeeder as n, AXCAiAssistSeeder as o, AXCAiManagementMockModule as p, AXCAiModelSeeder as q, resolveDelegatedAssistOptionModel as r, AXCAppTermDataSeeder as s, AXCAppVersionDataSeeder as t, AXCApplicationCategoryDataSeeder as u, AXCApplicationDataSeeder as v, AXCApplicationManagementMockModule as w, AXCAssessmentManagementMockModule as x, AXCAssetManagementMockModule as y, AXCAuthMockModule as z };
76347
+ //# sourceMappingURL=acorex-connectivity-mock-acorex-connectivity-mock-BwFZQ1Xw.mjs.map