@acorex/connectivity 21.0.0-next.65 → 21.0.0-next.67

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 (18) hide show
  1. package/fesm2022/{acorex-connectivity-mock-acorex-connectivity-mock--5Xrsmgy.mjs → acorex-connectivity-mock-acorex-connectivity-mock-0h4KR9DL.mjs} +1911 -748
  2. package/fesm2022/acorex-connectivity-mock-acorex-connectivity-mock-0h4KR9DL.mjs.map +1 -0
  3. package/fesm2022/{acorex-connectivity-mock-assign-to-manager.activity-NlqPDd5p.mjs → acorex-connectivity-mock-assign-to-manager.activity-DR_QQMhA.mjs} +2 -2
  4. package/fesm2022/{acorex-connectivity-mock-assign-to-manager.activity-NlqPDd5p.mjs.map → acorex-connectivity-mock-assign-to-manager.activity-DR_QQMhA.mjs.map} +1 -1
  5. package/fesm2022/{acorex-connectivity-mock-chat-generate-image.command-CzaHjSnU.mjs → acorex-connectivity-mock-chat-generate-image.command-D6J0xCjZ.mjs} +2 -4
  6. package/fesm2022/acorex-connectivity-mock-chat-generate-image.command-D6J0xCjZ.mjs.map +1 -0
  7. package/fesm2022/{acorex-connectivity-mock-chat-synthesize-speech.command-P5gOvT0K.mjs → acorex-connectivity-mock-chat-synthesize-speech.command-D66e7J-F.mjs} +5 -4
  8. package/fesm2022/acorex-connectivity-mock-chat-synthesize-speech.command-D66e7J-F.mjs.map +1 -0
  9. package/fesm2022/{acorex-connectivity-mock-chat-transcribe-speech.command-B1v1x3zx.mjs → acorex-connectivity-mock-chat-transcribe-speech.command-D_mclluL.mjs} +2 -2
  10. package/fesm2022/{acorex-connectivity-mock-chat-transcribe-speech.command-B1v1x3zx.mjs.map → acorex-connectivity-mock-chat-transcribe-speech.command-D_mclluL.mjs.map} +1 -1
  11. package/fesm2022/{acorex-connectivity-mock-user-roles-for-list-column.query-nadNnJKc.mjs → acorex-connectivity-mock-user-roles-for-list-column.query-BLkdnyel.mjs} +2 -2
  12. package/fesm2022/{acorex-connectivity-mock-user-roles-for-list-column.query-nadNnJKc.mjs.map → acorex-connectivity-mock-user-roles-for-list-column.query-BLkdnyel.mjs.map} +1 -1
  13. package/fesm2022/acorex-connectivity-mock.mjs +1 -1
  14. package/package.json +2 -2
  15. package/types/acorex-connectivity-mock.d.ts +76 -26
  16. package/fesm2022/acorex-connectivity-mock-acorex-connectivity-mock--5Xrsmgy.mjs.map +0 -1
  17. package/fesm2022/acorex-connectivity-mock-chat-generate-image.command-CzaHjSnU.mjs.map +0 -1
  18. package/fesm2022/acorex-connectivity-mock-chat-synthesize-speech.command-P5gOvT0K.mjs.map +0 -1
@@ -2,7 +2,7 @@ import { AXSafePipe } from '@acorex/core/pipes';
2
2
  import * as i2$2 from '@acorex/platform/auth';
3
3
  import { AXPSessionService, AXP_PERMISSION_DEFINITION_PROVIDER, AXPPermissionDefinitionService, 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
- import { AXPDataGenerator, AXP_DISTRIBUTED_EVENT_LISTENER_PROVIDER, AXPIconLogoConfig, AXPModuleManifestRegistry, AXPActivityLogProvider, AXP_ACTIVITY_LOG_PROVIDER, AXP_DATASOURCE_DEFINITION_PROVIDER, AXPDataSourceDefinitionProviderService, AXPPlatformScope, AXPExpressionEvaluatorService, provideLazyProvider } from '@acorex/platform/core';
5
+ import { AXPDataGenerator, AXPContextDefinitionProviderService, AXP_DISTRIBUTED_EVENT_LISTENER_PROVIDER, AXPIconLogoConfig, AXPModuleManifestRegistry, AXPActivityLogProvider, AXP_ACTIVITY_LOG_PROVIDER, AXP_DATASOURCE_DEFINITION_PROVIDER, AXPDataSourceDefinitionProviderService, AXPPlatformScope, AXPExpressionEvaluatorService, provideLazyProvider } from '@acorex/platform/core';
6
6
  import { runEntityQuery, filterSortEntityRows, computeEntityAggregates, AXP_ENTITY_STORAGE_BACKEND, AXPEntityStorageService, isAXPMiddlewareAbortError, AXPEntityResolver, collectEntityQuickSearchFieldPaths, AXP_ENTITY_DEFINITION_CRUD_SERVICE, AXPEntityService, AXP_ENTITY_DEFINITION_LOADER, axpCreateEntityAiToolInputDefaults, AXPMiddlewareAbortError, AXP_DATA_SEEDER_TOKEN, AXP_ENTITY_STORAGE_MIDDLEWARE, AXPEntityDefinitionRegistryService, eventDispatchMiddleware, buildAXPRecordWorkflowInfo, 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';
@@ -16,8 +16,9 @@ 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, axpAiChatMessageIsDelegatedReflectionExcluded, axpAiChatTextMessage, axpAiChatMessageGetText, AIMANAGEMENT_CHAT_GENERATE_IMAGE_COMMAND_KEY, AIMANAGEMENT_CHAT_TRANSCRIBE_SPEECH_COMMAND_KEY, AIMANAGEMENT_CHAT_SYNTHESIZE_SPEECH_COMMAND_KEY, axpAiChatToolResultBodyJson, getAiChatCommandLlmParametersOverride, AXPAiManagementSettings, axpAiChatToolOrAgentResultBodyJson, AXPAiChatToolRunContextService, modelRowHasPurpose, isChatPurposeModelRow, resolveAgentOutputContract, resolveOutputTranscriptSegment, validateAgainstContract, axpAiAgentOutputContractUsesStructuredFinalize, axpAiAgentOutputContractStructuredRetryCap, extractLastAssistantStructuredParts, buildStructuredOutputRetryUserText, axpAiParseSupervisorAgentToolName as axpAiParseSupervisorAgentToolName$1, deriveProviderResponseFormat, axpAiAgentOutputContractOmitsRoleBaseline, axpAiDelegatedAgentOutcomeResponsesPlainText, AXPAiEngine, AXPAiOutputContractResolveService, AXPAiAssistChatModelCatalogService, axpAiAssistInitialMessagesToTranscript, axpAiChatUserMessage } from '@acorex/modules/ai-management';
19
+ import { RootConfig, axpAiChatMessageIsDelegatedReflectionExcluded, axpAiChatTextMessage, axpAiChatMessageGetText, AIMANAGEMENT_CHAT_GENERATE_IMAGE_COMMAND_KEY, AIMANAGEMENT_CHAT_TRANSCRIBE_SPEECH_COMMAND_KEY, AIMANAGEMENT_CHAT_SYNTHESIZE_SPEECH_COMMAND_KEY, axpAiChatToolResultBodyJson, getAiChatCommandLlmParametersOverride, AXPAiManagementSettings, axpAiChatToolOrAgentResultBodyJson, AXPAiChatToolRunContextService, modelRowHasPurpose, isChatPurposeModelRow, resolveAgentOutputContract, resolveOutputTranscriptSegment, validateAgainstContract, axpAiAgentOutputContractUsesStructuredFinalize, axpAiAgentOutputContractStructuredRetryCap, extractLastAssistantStructuredParts, buildStructuredOutputRetryUserText, axpAiParseSupervisorAgentToolName as axpAiParseSupervisorAgentToolName$1, deriveProviderResponseFormat, axpAiAgentOutputContractOmitsRoleBaseline, axpAiDelegatedAgentOutcomeResponsesPlainText, axpBuildDelegatedAgentRunInputSnapshot, axpSanitizeLastProviderPayloadForPersistence, AXPAiEngine, AXPAiOutputContractResolveService, AXPAiPlatformRuntimeContextBuilder, AXPAiAssistChatModelCatalogService, axpAiAssistInitialMessagesToTranscript, axpAiChatUserMessage } from '@acorex/modules/ai-management';
20
20
  import { RootConfig as RootConfig$1 } from '@acorex/modules/platform-management';
21
+ import { castArray, isString, trim, defaultTo, get, isArray, set } from 'lodash-es';
21
22
  import { RootConfig as RootConfig$2, AXMPermissionsKeys, AXMApplicationService, AXMEditionService } from '@acorex/modules/application-management';
22
23
  import { AXMAssetManagementFeatureKeys, RootConfig as RootConfig$4, AXMAssetStatus } from '@acorex/modules/asset-management';
23
24
  import { AXMAssessmentManagementFeatureKeys, RootConfig as RootConfig$3, AXMAssessmentManagementPermissionKeys } from '@acorex/modules/assessment-management';
@@ -40,7 +41,6 @@ import { RootConfig as RootConfig$9, resolveTextTemplateLocalizedString, replace
40
41
  import { conversationSharedStorage, axConversationIndexedDbStorage, normalizeFilePayload, normalizeVideoPayload, normalizeImagePayload, AXConversationAiResponderService } from '@acorex/components/conversation2';
41
42
  import { AXMNotificationEntityService, RootConfig as RootConfig$q, AXMNotificationEntityServiceImpl, AXMNotificationRealtimeService, NOTIFICATION_MANAGEMENT_EMAIL_SEND_COMMAND_KEY } from '@acorex/modules/notification-management';
42
43
  import { AXToastService } from '@acorex/components/toast';
43
- import { trim, defaultTo, get, castArray, isArray, isString, set } from 'lodash-es';
44
44
  import { Observable, filter, pairwise, map, merge } from 'rxjs';
45
45
  import { RootConfig as RootConfig$b } from '@acorex/modules/customer-management';
46
46
  import { RootConfig as RootConfig$c } from '@acorex/modules/dashboard-management';
@@ -84,6 +84,7 @@ import { Router } from '@angular/router';
84
84
  import { AXPWorkflowManager, AXPWorkflowDefinitionService, AXPActivityDefinitionService, AXP_WORKFLOW_PROVIDER, WorkflowExpressionScopeService, AXPWorkflowEngineError, AXP_WORKFLOW_ERROR_CODES, AXP_WORKFLOW_ENGINE } from '@acorex/platform/workflow';
85
85
  import { AXCalendarService } from '@acorex/core/date-time';
86
86
  import { RootConfig as RootConfig$B } from '@acorex/modules/maintenance-management';
87
+ import { RootConfig as RootConfig$C, AXMHazardRegisterContextType } from '@acorex/modules/workplacesafety-management';
87
88
  import { AXCExternalAuthorizationService } from '@acorex/connectivity/utils';
88
89
 
89
90
  /**
@@ -4004,7 +4005,7 @@ const SCHEMA_DEFINITIONS_MOCK = [
4004
4005
  name: 'file',
4005
4006
  title: 'File',
4006
4007
  interface: {
4007
- name: 'file-uploader',
4008
+ name: 'attachments',
4008
4009
  title: 'File',
4009
4010
  options: {
4010
4011
  accept: ['*/*'],
@@ -5756,7 +5757,7 @@ const COMMAND_REGISTRY_SEED = [
5756
5757
  "definition": {
5757
5758
  "name": "AssessmentManagement.Questionnaire:Preview",
5758
5759
  "active": true,
5759
- "description": "PreviewQuestionnaireCommand opens a questionnaire preview dialog from PreviewQuestionnaireCommandInput (questionnaireId required; optional questionnaireTitle).",
5760
+ "description": "AXPPreviewQuestionnaireCommand opens a questionnaire preview dialog from AXPPreviewQuestionnaireCommandInput (questionnaireId required; optional questionnaireTitle).",
5760
5761
  "inputOptionDefinitions": [
5761
5762
  {
5762
5763
  "name": "questionnaireId",
@@ -6065,26 +6066,6 @@ const COMMAND_REGISTRY_SEED = [
6065
6066
  },
6066
6067
  "description": "Original prompt text."
6067
6068
  },
6068
- {
6069
- "name": "mimeType",
6070
- "title": "MIME type",
6071
- "interface": {
6072
- "name": "text-editor",
6073
- "title": "MIME type",
6074
- "options": {}
6075
- },
6076
- "description": "Image MIME type of the stored file (required for chat file replay)."
6077
- },
6078
- {
6079
- "name": "name",
6080
- "title": "File name",
6081
- "interface": {
6082
- "name": "text-editor",
6083
- "title": "File name",
6084
- "options": {}
6085
- },
6086
- "description": "Stored file name shown in chat replay."
6087
- },
6088
6069
  {
6089
6070
  "name": "imageUrl",
6090
6071
  "title": "Image URL",
@@ -6123,9 +6104,21 @@ const COMMAND_REGISTRY_SEED = [
6123
6104
  "name": "model",
6124
6105
  "title": "Model",
6125
6106
  "interface": {
6126
- "name": "text-editor",
6107
+ "name": "lookup-editor",
6127
6108
  "title": "Model",
6128
- "options": {}
6109
+ "options": {
6110
+ "entity": "AiManagement.AiModel",
6111
+ "textField": "title",
6112
+ "valueField": "id",
6113
+ "look": "select",
6114
+ "allowSearch": true,
6115
+ "columns": ["title", "name"],
6116
+ "filter": {
6117
+ "field": "modelPurposes",
6118
+ "operator": { "type": "contains" },
6119
+ "value": "tts"
6120
+ }
6121
+ }
6129
6122
  },
6130
6123
  "description": "Optional AiModel catalog row id (tts purpose). When omitted, uses delegatedAgents[].options.model for the active delegated specialist (agentId in run context)."
6131
6124
  },
@@ -6185,16 +6178,6 @@ const COMMAND_REGISTRY_SEED = [
6185
6178
  "options": {}
6186
6179
  },
6187
6180
  "description": "Source text that was synthesized."
6188
- },
6189
- {
6190
- "name": "mimeType",
6191
- "title": "MIME type",
6192
- "interface": {
6193
- "name": "text-editor",
6194
- "title": "MIME type",
6195
- "options": {}
6196
- },
6197
- "description": "Audio MIME type of the stored file."
6198
6181
  }
6199
6182
  ],
6200
6183
  "catalogTitle": "Synthesize speech (chat)",
@@ -6224,9 +6207,21 @@ const COMMAND_REGISTRY_SEED = [
6224
6207
  "name": "model",
6225
6208
  "title": "Model",
6226
6209
  "interface": {
6227
- "name": "text-editor",
6210
+ "name": "lookup-editor",
6228
6211
  "title": "Model",
6229
- "options": {}
6212
+ "options": {
6213
+ "entity": "AiManagement.AiModel",
6214
+ "textField": "title",
6215
+ "valueField": "id",
6216
+ "look": "select",
6217
+ "allowSearch": true,
6218
+ "columns": ["title", "name"],
6219
+ "filter": {
6220
+ "field": "modelPurposes",
6221
+ "operator": { "type": "contains" },
6222
+ "value": "speech"
6223
+ }
6224
+ }
6230
6225
  },
6231
6226
  "description": "Optional AiModel catalog row id (speech purpose). When omitted, uses delegatedAgents[].options.model for the active delegated specialist (agentId in run context)."
6232
6227
  },
@@ -7337,7 +7332,7 @@ const COMMAND_REGISTRY_SEED = [
7337
7332
  "catalogTitle": "Edit file uploader item",
7338
7333
  "executionMode": "frontend",
7339
7334
  "outcomesDefinitionJson": "{\n \"mode\": \"static\",\n \"values\": [\n \"success\",\n \"failure\"\n ]\n}",
7340
- "aiMetadataJson": "{\n \"tags\": [\n \"file-uploader\",\n \"edit\"\n ]\n}",
7335
+ "aiMetadataJson": "{\n \"tags\": [\n \"attachments\",\n \"edit\"\n ]\n}",
7341
7336
  "categories": [
7342
7337
  {
7343
7338
  "name": "file-widget",
@@ -8611,39 +8606,19 @@ const COMMAND_REGISTRY_SEED = [
8611
8606
  {
8612
8607
  "id": "cmd_62a31dc90e5e",
8613
8608
  "definition": {
8614
- "name": "workflow-activity:collect-signature",
8609
+ "name": "workflow-activity:sign-off",
8615
8610
  "active": true,
8616
- "description": "CollectSignatureActivity builds a layout-builder dialog with note + SignatureBox; translated message defaults from input.message or translation key for default message. Cancel/action cancel → success true, data.signature \"\", signedAt ISO, metadata.outcome Cancelled. Submit with signature success true, data.signature/note/signedAt, metadata.outcome Signed. Catch → success false, metadata.outcome Cancelled.",
8611
+ "description": "SignOffActivity opens a layout-builder dialog with optional note + required SignatureBox. Cancel → success true, empty signature, metadata.outcome Cancelled. Submit → data.signature/note/signedAt, metadata.outcome Signed.",
8617
8612
  "inputOptionDefinitions": [
8618
8613
  {
8619
- "name": "signatureRequestId",
8620
- "title": "Signature request ID",
8621
- "interface": {
8622
- "name": "text-editor",
8623
- "title": "Signature request ID",
8624
- "options": {}
8625
- },
8626
- "description": "Signature request identifier (logged; dialog does not persist it).",
8627
- "validations": [
8628
- {
8629
- "rule": "required"
8630
- }
8631
- ]
8632
- },
8633
- {
8634
- "name": "signerId",
8635
- "title": "Signer ID",
8614
+ "name": "message",
8615
+ "title": "Message",
8636
8616
  "interface": {
8637
- "name": "text-editor",
8638
- "title": "Signer ID",
8617
+ "name": "large-text-editor",
8618
+ "title": "Message",
8639
8619
  "options": {}
8640
8620
  },
8641
- "description": "Signer user id (logged).",
8642
- "validations": [
8643
- {
8644
- "rule": "required"
8645
- }
8646
- ]
8621
+ "description": "Optional dialog message; translated if translation key."
8647
8622
  },
8648
8623
  {
8649
8624
  "name": "refId",
@@ -8653,12 +8628,7 @@ const COMMAND_REGISTRY_SEED = [
8653
8628
  "title": "Reference ID",
8654
8629
  "options": {}
8655
8630
  },
8656
- "description": "Entity record id for the signed document context.",
8657
- "validations": [
8658
- {
8659
- "rule": "required"
8660
- }
8661
- ]
8631
+ "description": "Optional entity record id for workflow context."
8662
8632
  },
8663
8633
  {
8664
8634
  "name": "refType",
@@ -8668,22 +8638,7 @@ const COMMAND_REGISTRY_SEED = [
8668
8638
  "title": "Reference type",
8669
8639
  "options": {}
8670
8640
  },
8671
- "description": "module.entity style reference type.",
8672
- "validations": [
8673
- {
8674
- "rule": "required"
8675
- }
8676
- ]
8677
- },
8678
- {
8679
- "name": "message",
8680
- "title": "Message",
8681
- "interface": {
8682
- "name": "large-text-editor",
8683
- "title": "Message",
8684
- "options": {}
8685
- },
8686
- "description": "Optional message shown in dialog; translated if translation key."
8641
+ "description": "Optional module.entity reference type."
8687
8642
  }
8688
8643
  ],
8689
8644
  "outputOptionDefinitions": [
@@ -8718,10 +8673,83 @@ const COMMAND_REGISTRY_SEED = [
8718
8673
  "description": "ISO timestamp string."
8719
8674
  }
8720
8675
  ],
8721
- "catalogTitle": "Collect signature",
8676
+ "catalogTitle": "Sign off",
8722
8677
  "executionMode": "frontend",
8723
8678
  "outcomesDefinitionJson": "{\n \"mode\": \"static\",\n \"values\": [\n \"Signed\",\n \"Cancelled\"\n ]\n}",
8724
- "aiMetadataJson": "{\n \"shortDescription\": \"Interactive signature capture dialog.\",\n \"tags\": [\n \"workflow\",\n \"signature\"\n ]\n}",
8679
+ "aiMetadataJson": "{\n \"shortDescription\": \"Interactive sign-off dialog with required signature.\",\n \"tags\": [\n \"workflow\",\n \"sign-off\",\n \"approval\"\n ]\n}",
8680
+ "categories": [
8681
+ {
8682
+ "name": "workflow",
8683
+ "order": 5,
8684
+ "title": "Workflow"
8685
+ }
8686
+ ]
8687
+ }
8688
+ },
8689
+ {
8690
+ "id": "cmd_rejection_reason_signoff",
8691
+ "definition": {
8692
+ "name": "workflow-activity:rejection-reason",
8693
+ "active": true,
8694
+ "description": "RejectionReasonActivity opens a rejection dialog with required reason (default) and optional note. Cancel → empty reason, metadata.outcome Cancelled. Submit → data.reason/note/rejectedAt, metadata.outcome Submitted.",
8695
+ "inputOptionDefinitions": [
8696
+ {
8697
+ "name": "message",
8698
+ "title": "Message",
8699
+ "interface": {
8700
+ "name": "large-text-editor",
8701
+ "title": "Message",
8702
+ "options": {}
8703
+ },
8704
+ "description": "Optional dialog message; translated if translation key."
8705
+ },
8706
+ {
8707
+ "name": "requireReason",
8708
+ "title": "Require reason",
8709
+ "interface": {
8710
+ "name": "toggle-editor",
8711
+ "title": "Require reason",
8712
+ "options": {}
8713
+ },
8714
+ "description": "When true (default), reason must be non-empty."
8715
+ }
8716
+ ],
8717
+ "outputOptionDefinitions": [
8718
+ {
8719
+ "name": "reason",
8720
+ "title": "Reason",
8721
+ "interface": {
8722
+ "name": "large-text-editor",
8723
+ "title": "Reason",
8724
+ "options": {}
8725
+ },
8726
+ "description": "Rejection reason (empty when cancelled)."
8727
+ },
8728
+ {
8729
+ "name": "note",
8730
+ "title": "Note",
8731
+ "interface": {
8732
+ "name": "large-text-editor",
8733
+ "title": "Note",
8734
+ "options": {}
8735
+ },
8736
+ "description": "Optional additional note."
8737
+ },
8738
+ {
8739
+ "name": "rejectedAt",
8740
+ "title": "Rejected at",
8741
+ "interface": {
8742
+ "name": "text-editor",
8743
+ "title": "Rejected at",
8744
+ "options": {}
8745
+ },
8746
+ "description": "ISO timestamp when rejection was captured."
8747
+ }
8748
+ ],
8749
+ "catalogTitle": "Rejection reason",
8750
+ "executionMode": "frontend",
8751
+ "outcomesDefinitionJson": "{\n \"mode\": \"static\",\n \"values\": [\n \"Submitted\",\n \"Cancelled\"\n ]\n}",
8752
+ "aiMetadataJson": "{\n \"shortDescription\": \"Rejection reason dialog for workflow reject branches.\",\n \"tags\": [\n \"workflow\",\n \"sign-off\",\n \"rejection\"\n ]\n}",
8725
8753
  "categories": [
8726
8754
  {
8727
8755
  "name": "workflow",
@@ -12419,11 +12447,11 @@ const WIDGET_CATALOG_SEED = [
12419
12447
  {
12420
12448
  "id": "wgt_75f9bff47cc2",
12421
12449
  "definition": {
12422
- "name": "file-uploader",
12450
+ "name": "attachments",
12423
12451
  "active": true,
12424
- "metadataJson": "{\n \"name\": \"file-uploader\",\n \"title\": \"@platform-layout-widgets:widgets.file-uploader.title\",\n \"description\": \"@platform-layout-widgets:widgets.file-uploader.description\",\n \"icon\": \"fa-light fa-files\",\n \"categories\": [\n {\n \"name\": \"advance\",\n \"order\": 4,\n \"title\": \"@platform-layout-widgets:categories.advance.title\"\n }\n ],\n \"subCategory\": {\n \"name\": \"advance-media\",\n \"order\": 1,\n \"title\": \"@platform-layout-widgets:subcategories.advance-media.title\"\n },\n \"groups\": [\n \"form-element\"\n ],\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\": \"multiple\",\n \"title\": \"Multiple\",\n \"interface\": {\n \"name\": \"toggle-editor\"\n }\n },\n {\n \"name\": \"downloadable\",\n \"title\": \"Downloadable\",\n \"interface\": {\n \"name\": \"toggle-editor\"\n }\n },\n {\n \"name\": \"readonly\",\n \"title\": \"Readonly\",\n \"interface\": {\n \"name\": \"toggle-editor\"\n }\n },\n {\n \"name\": \"description\",\n \"title\": \"Description\",\n \"interface\": {\n \"name\": \"text-editor\"\n }\n },\n {\n \"name\": \"accept\",\n \"title\": \"Accept\",\n \"interface\": {\n \"name\": \"text-editor\"\n }\n },\n {\n \"name\": \"fileEditable\",\n \"title\": \"File Editable\",\n \"interface\": {\n \"name\": \"toggle-editor\"\n }\n },\n {\n \"name\": \"enableTitleDescription\",\n \"title\": \"Enable Title & Description\",\n \"interface\": {\n \"name\": \"toggle-editor\"\n }\n },\n {\n \"name\": \"showEditDialogAfterSelect\",\n \"title\": \"Show Edit Dialog After File Select\",\n \"interface\": {\n \"name\": \"toggle-editor\"\n }\n },\n {\n \"name\": \"maxFileSize\",\n \"title\": \"Max File Size (bytes)\",\n \"interface\": {\n \"name\": \"number-editor\"\n }\n },\n {\n \"name\": \"plugins\",\n \"title\": \"Plugins / excludePlugins\",\n \"description\": \"AXPFileUploaderWidgetEditOptions / designer options include plugins and excludePlugins; not declared as designer properties on AXPFileUploaderWidget.properties.\",\n \"interface\": {\n \"name\": \"json\"\n }\n }\n ],\n \"outputs\": [\n {\n \"name\": \"boundValue\",\n \"title\": \"File list\",\n \"description\": \"AXPFileListItem[] | undefined on edit; view filters out status === deleted; column uses rawValue as AXPFileListItem[] for count + popup.\",\n \"interface\": {\n \"name\": \"json\"\n }\n }\n ],\n \"ai\": {\n \"tags\": [\n \"editor\",\n \"file\",\n \"upload\",\n \"attachment\"\n ],\n \"instruction\": \"Use when the answer involves file attachments: list, upload, or download. Prefer when the user references documents or media beyond inline text. Hooks (configure / beforeFilesAdded / afterFilesAdded) are implemented in the edit component.\",\n \"usage\": {\n \"whenToUse\": [\n \"Entity fields that store multiple file metadata rows with optional title/description per file.\"\n ],\n \"avoidWhen\": [\n \"Single circular avatar — avatar widget.\"\n ]\n },\n \"renderSurfaces\": [\n {\n \"mode\": \"edit\",\n \"summary\": \"AXPValueWidgetComponent<AXPFileListItem[] | undefined>: dropdown upload actions, axp-file-list, AXPHookService integration for FileUploaderWebhookKeys.\"\n },\n {\n \"mode\": \"view\",\n \"summary\": \"AXPValueWidgetComponent<AXPFileListItem[]>: readonly axp-file-list with deleted rows filtered out.\"\n },\n {\n \"mode\": \"column\",\n \"summary\": \"AXPColumnWidgetComponent<AXPFileListItem[]>: link showing file count; AXPFileUploaderWidgetService.showFileList.\"\n },\n {\n \"mode\": \"designer\",\n \"summary\": \"Reuses file-uploader-widget-edit.\"\n }\n ]\n }\n}",
12425
- "catalogTitle": "@platform-layout-widgets:widgets.file-uploader.title",
12426
- "description": "@platform-layout-widgets:widgets.file-uploader.description"
12452
+ "metadataJson": "{\n \"name\": \"attachments\",\n \"title\": \"@platform-layout-widgets:widgets.attachments.title\",\n \"description\": \"@platform-layout-widgets:widgets.attachments.description\",\n \"icon\": \"fa-light fa-files\",\n \"categories\": [\n {\n \"name\": \"advance\",\n \"order\": 4,\n \"title\": \"@platform-layout-widgets:categories.advance.title\"\n }\n ],\n \"subCategory\": {\n \"name\": \"advance-media\",\n \"order\": 1,\n \"title\": \"@platform-layout-widgets:subcategories.advance-media.title\"\n },\n \"groups\": [\n \"form-element\"\n ],\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\": \"multiple\",\n \"title\": \"Multiple\",\n \"interface\": {\n \"name\": \"toggle-editor\"\n }\n },\n {\n \"name\": \"downloadable\",\n \"title\": \"Downloadable\",\n \"interface\": {\n \"name\": \"toggle-editor\"\n }\n },\n {\n \"name\": \"readonly\",\n \"title\": \"Readonly\",\n \"interface\": {\n \"name\": \"toggle-editor\"\n }\n },\n {\n \"name\": \"description\",\n \"title\": \"Description\",\n \"interface\": {\n \"name\": \"text-editor\"\n }\n },\n {\n \"name\": \"accept\",\n \"title\": \"Accept\",\n \"interface\": {\n \"name\": \"text-editor\"\n }\n },\n {\n \"name\": \"fileEditable\",\n \"title\": \"File Editable\",\n \"interface\": {\n \"name\": \"toggle-editor\"\n }\n },\n {\n \"name\": \"enableTitleDescription\",\n \"title\": \"Enable Title & Description\",\n \"interface\": {\n \"name\": \"toggle-editor\"\n }\n },\n {\n \"name\": \"showEditDialogAfterSelect\",\n \"title\": \"Show Edit Dialog After File Select\",\n \"interface\": {\n \"name\": \"toggle-editor\"\n }\n },\n {\n \"name\": \"maxFileSize\",\n \"title\": \"Max File Size (bytes)\",\n \"interface\": {\n \"name\": \"number-editor\"\n }\n },\n {\n \"name\": \"plugins\",\n \"title\": \"Plugins / excludePlugins\",\n \"description\": \"AXPFileUploaderWidgetEditOptions / designer options include plugins and excludePlugins; not declared as designer properties on AXPFileUploaderWidget.properties.\",\n \"interface\": {\n \"name\": \"json\"\n }\n }\n ],\n \"outputs\": [\n {\n \"name\": \"boundValue\",\n \"title\": \"File list\",\n \"description\": \"AXPFileListItem[] | undefined on edit; view filters out status === deleted; column uses rawValue as AXPFileListItem[] for count + popup.\",\n \"interface\": {\n \"name\": \"json\"\n }\n }\n ],\n \"ai\": {\n \"tags\": [\n \"editor\",\n \"file\",\n \"upload\",\n \"attachment\"\n ],\n \"instruction\": \"Use when the answer involves file attachments: list, upload, or download. Prefer when the user references documents or media beyond inline text. Hooks (configure / beforeFilesAdded / afterFilesAdded) are implemented in the edit component.\",\n \"usage\": {\n \"whenToUse\": [\n \"Entity fields that store multiple file metadata rows with optional title/description per file.\"\n ],\n \"avoidWhen\": [\n \"Single circular avatar — avatar widget.\"\n ]\n },\n \"renderSurfaces\": [\n {\n \"mode\": \"edit\",\n \"summary\": \"AXPValueWidgetComponent<AXPFileListItem[] | undefined>: dropdown upload actions, axp-file-list, AXPHookService integration for FileUploaderWebhookKeys.\"\n },\n {\n \"mode\": \"view\",\n \"summary\": \"AXPValueWidgetComponent<AXPFileListItem[]>: readonly axp-file-list with deleted rows filtered out.\"\n },\n {\n \"mode\": \"column\",\n \"summary\": \"AXPColumnWidgetComponent<AXPFileListItem[]>: link showing file count; AXPFileUploaderWidgetService.showFileList.\"\n },\n {\n \"mode\": \"designer\",\n \"summary\": \"Reuses file-uploader-widget-edit.\"\n }\n ]\n }\n}",
12453
+ "catalogTitle": "@platform-layout-widgets:widgets.attachments.title",
12454
+ "description": "@platform-layout-widgets:widgets.attachments.description"
12427
12455
  }
12428
12456
  },
12429
12457
  {
@@ -13173,6 +13201,8 @@ const AXMAiOpenAiEndpointStableIds = {
13173
13201
  demis: 'e0000001-0000-4000-8000-000000000002',
13174
13202
  lmStudio: 'e0000001-0000-4000-8000-000000000003',
13175
13203
  ollama: 'e0000001-0000-4000-8000-000000000004',
13204
+ gapGpt: 'e0000001-0000-4000-8000-000000000005',
13205
+ openRouter: 'e0000001-0000-4000-8000-000000000006',
13176
13206
  };
13177
13207
  //#endregion
13178
13208
  //#region ---- Mock API key decoding ----
@@ -13222,6 +13252,22 @@ const OPEN_AI_ENDPOINT_MOCK = [
13222
13252
  stream: false,
13223
13253
  isDisabled: true,
13224
13254
  },
13255
+ {
13256
+ id: AXMAiOpenAiEndpointStableIds.gapGpt,
13257
+ title: M$1d('Gap Gpt', 'گپ جی پی تی'),
13258
+ description: M$1d('Gap Gpt API', 'API گپ جی پی تی'),
13259
+ apiBase: 'https://api.gapgpt.app/v1',
13260
+ apiKey: 'sk-fxY5yP4ACs6tHZHj9vKeZ5EtVIJ4szMtaK5pBP7hoDqV3vrU',
13261
+ stream: true,
13262
+ },
13263
+ {
13264
+ id: AXMAiOpenAiEndpointStableIds.openRouter,
13265
+ title: M$1d('OpenRouter', 'اوپن‌روتر'),
13266
+ description: M$1d('OpenRouter OpenAI-compatible API gateway. Base URL ends at /v1.', 'درگاه API سازگار با OpenAI در OpenRouter. آدرس پایه با /v1 تمام می‌شود.'),
13267
+ apiBase: 'https://openrouter.ai/api/v1',
13268
+ apiKey: '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',
13269
+ stream: true,
13270
+ },
13225
13271
  ];
13226
13272
  //#endregion
13227
13273
 
@@ -13250,6 +13296,62 @@ const AXMAiModelStableIds = {
13250
13296
  openaiWhisper1: 'a0000001-0000-4000-8000-000000000040',
13251
13297
  /** OpenAI audio/speech API (`tts-1`). */
13252
13298
  openaiTts1: 'a0000001-0000-4000-8000-000000000042',
13299
+ /** GapGPT Qwen 3.5 (`gapgpt-qwen-3.5`). */
13300
+ gapGptQwen35: 'a0000001-0000-4000-8000-000000000043',
13301
+ gapGptQwen35Thinking: 'a0000001-0000-4000-8000-000000000044',
13302
+ gapGptQwen36: 'a0000001-0000-4000-8000-000000000045',
13303
+ gapGptQwen36Thinking: 'a0000001-0000-4000-8000-000000000046',
13304
+ gapGptGpt52: 'a0000001-0000-4000-8000-000000000047',
13305
+ gapGptGpt52ChatLatest: 'a0000001-0000-4000-8000-000000000048',
13306
+ gapGptGpt52Codex: 'a0000001-0000-4000-8000-000000000049',
13307
+ gapGptGpt52Pro: 'a0000001-0000-4000-8000-00000000004a',
13308
+ gapGptGpt53ChatLatest: 'a0000001-0000-4000-8000-00000000004b',
13309
+ gapGptGpt53Codex: 'a0000001-0000-4000-8000-00000000004c',
13310
+ gapGptGpt53CodexSpark: 'a0000001-0000-4000-8000-00000000004d',
13311
+ gapGptClaudeOpus41: 'a0000001-0000-4000-8000-00000000004e',
13312
+ gapGptClaudeOpus4: 'a0000001-0000-4000-8000-00000000004f',
13313
+ gapGptClaudeOpus45: 'a0000001-0000-4000-8000-000000000050',
13314
+ gapGptZImage: 'a0000001-0000-4000-8000-000000000051',
13315
+ gapGptGptImage2: 'a0000001-0000-4000-8000-000000000052',
13316
+ gapGptGemini3ProImagePreview: 'a0000001-0000-4000-8000-000000000053',
13317
+ gapGptGptImage1Mini: 'a0000001-0000-4000-8000-000000000054',
13318
+ gapGptDalle3: 'a0000001-0000-4000-8000-000000000055',
13319
+ gapGptGemini25FlashImage: 'a0000001-0000-4000-8000-000000000056',
13320
+ gapGptGemini31FlashImagePreview: 'a0000001-0000-4000-8000-000000000057',
13321
+ gapGptImagen40Fast: 'a0000001-0000-4000-8000-000000000058',
13322
+ gapGptImagen40Ultra: 'a0000001-0000-4000-8000-000000000059',
13323
+ gapGptWhisper1: 'a0000001-0000-4000-8000-00000000005a',
13324
+ gapGptOpenAiWhisper1: 'a0000001-0000-4000-8000-00000000005b',
13325
+ gapGptGpt4oMiniTts: 'a0000001-0000-4000-8000-00000000005c',
13326
+ gapGptTts1: 'a0000001-0000-4000-8000-00000000005d',
13327
+ gapGptGemini25FlashPreviewTts: 'a0000001-0000-4000-8000-00000000005e',
13328
+ gapGptGemini25ProPreviewTts: 'a0000001-0000-4000-8000-00000000005f',
13329
+ gapGptGemma327bIt: 'a0000001-0000-4000-8000-000000000060',
13330
+ gapGptDeepseekV4Flash: 'a0000001-0000-4000-8000-000000000061',
13331
+ gapGptGemini25FlashLite: 'a0000001-0000-4000-8000-000000000062',
13332
+ gapGptGpt41Nano: 'a0000001-0000-4000-8000-000000000063',
13333
+ gapGptGpt5Nano: 'a0000001-0000-4000-8000-000000000064',
13334
+ gapGptQwen3235bA22b: 'a0000001-0000-4000-8000-000000000065',
13335
+ gapGptGpt4oMini: 'a0000001-0000-4000-8000-000000000066',
13336
+ gapGptGemini31FlashLitePreview: 'a0000001-0000-4000-8000-000000000067',
13337
+ gapGptGeminiFlashLiteLatest: 'a0000001-0000-4000-8000-000000000068',
13338
+ gapGptGrok3Mini: 'a0000001-0000-4000-8000-000000000069',
13339
+ gapGptGpt41Mini: 'a0000001-0000-4000-8000-00000000006a',
13340
+ gemini25Pro: 'a0000001-0000-4000-8000-000000000070',
13341
+ gemini25FlashLite: 'a0000001-0000-4000-8000-000000000071',
13342
+ gemini35Flash: 'a0000001-0000-4000-8000-000000000072',
13343
+ gemini31ProPreview: 'a0000001-0000-4000-8000-000000000073',
13344
+ gemini3FlashPreview: 'a0000001-0000-4000-8000-000000000074',
13345
+ gemini31FlashLite: 'a0000001-0000-4000-8000-000000000075',
13346
+ gemini25FlashImage: 'a0000001-0000-4000-8000-000000000076',
13347
+ gemini3ProImagePreview: 'a0000001-0000-4000-8000-000000000077',
13348
+ gemini31FlashImagePreview: 'a0000001-0000-4000-8000-000000000078',
13349
+ imagen40FastGenerate001: 'a0000001-0000-4000-8000-000000000079',
13350
+ imagen40UltraGenerate001: 'a0000001-0000-4000-8000-00000000007a',
13351
+ gemini25FlashPreviewTts: 'a0000001-0000-4000-8000-00000000007b',
13352
+ gemini25ProPreviewTts: 'a0000001-0000-4000-8000-00000000007c',
13353
+ openrouterOwlAlpha: 'a0000001-0000-4000-8000-00000000007d',
13354
+ openrouterQwen3Next80bA3bInstructFree: 'a0000001-0000-4000-8000-00000000007e',
13253
13355
  };
13254
13356
  //#endregion
13255
13357
  //#region ---- Lookup snapshots (avoid circular import with endpoint mock) ----
@@ -13263,11 +13365,116 @@ function mockOpenAiEndpointSnapshot(endpointId) {
13263
13365
  return { id: endpointId, title: M$1c('LM Studio', 'LM Studio') };
13264
13366
  case AXMAiOpenAiEndpointStableIds.ollama:
13265
13367
  return { id: endpointId, title: M$1c('Ollama', 'Ollama') };
13368
+ case AXMAiOpenAiEndpointStableIds.gapGpt:
13369
+ return { id: endpointId, title: M$1c('Gap Gpt', 'گپ جی پی تی') };
13370
+ case AXMAiOpenAiEndpointStableIds.openRouter:
13371
+ return { id: endpointId, title: M$1c('OpenRouter', 'اوپن‌روتر') };
13266
13372
  default:
13267
13373
  return { id: endpointId, title: M$1c('Unknown Endpoint', 'نقطه پایان نامشخص') };
13268
13374
  }
13269
13375
  }
13270
13376
  //#endregion
13377
+ //#region ---- GapGPT catalog helpers ----
13378
+ const GAP_GPT_ENDPOINT = AXMAiOpenAiEndpointStableIds.gapGpt;
13379
+ const GAP_GPT_ENDPOINT_SNAPSHOT = () => mockOpenAiEndpointSnapshot(GAP_GPT_ENDPOINT);
13380
+ /**
13381
+ * Builds a GapGPT-routed OpenAI-compatible catalog row (USD per 1M tokens from GapGPT pricing tables).
13382
+ */
13383
+ function gapGptCatalogModel(id, name, titleEn, titleFa, modelPurposes, pricing) {
13384
+ return {
13385
+ id,
13386
+ name,
13387
+ title: M$1c(titleEn, titleFa),
13388
+ description: M$1c(`GapGPT pricing catalog: ${name}`, `کاتالوگ قیمت گپ‌جی‌پی‌تی: ${name}`),
13389
+ chatTransport: 'openai',
13390
+ openAiEndpointId: GAP_GPT_ENDPOINT,
13391
+ openAiEndpoint: GAP_GPT_ENDPOINT_SNAPSHOT(),
13392
+ modelPurposes,
13393
+ ...pricing,
13394
+ };
13395
+ }
13396
+ /** GapGPT-hosted models from the public pricing page (chat, image, speech, TTS). */
13397
+ const GAP_GPT_PRICING_CATALOG_MOCK = [
13398
+ gapGptCatalogModel(AXMAiModelStableIds.gapGptQwen35, 'gapgpt-qwen-3.5', 'Qwen 3.5 (GapGPT)', 'Qwen 3.5 (گپ‌جی‌پی‌تی)', ['chat', 'vision'], { inputPricePerMillion: 0.25, outputPricePerMillion: 2 }),
13399
+ gapGptCatalogModel(AXMAiModelStableIds.gapGptQwen35Thinking, 'gapgpt-qwen-3.5-thinking', 'Qwen 3.5 Thinking (GapGPT)', 'Qwen 3.5 Thinking (گپ‌جی‌پی‌تی)', ['chat', 'vision'], { inputPricePerMillion: 0.25, outputPricePerMillion: 2 }),
13400
+ gapGptCatalogModel(AXMAiModelStableIds.gapGptQwen36, 'gapgpt-qwen-3.6', 'Qwen 3.6 (GapGPT)', 'Qwen 3.6 (گپ‌جی‌پی‌تی)', ['chat', 'vision'], { inputPricePerMillion: 0.25, outputPricePerMillion: 2 }),
13401
+ gapGptCatalogModel(AXMAiModelStableIds.gapGptQwen36Thinking, 'gapgpt-qwen-3.6-thinking', 'Qwen 3.6 Thinking (GapGPT)', 'Qwen 3.6 Thinking (گپ‌جی‌پی‌تی)', ['chat', 'vision'], { inputPricePerMillion: 0.25, outputPricePerMillion: 2 }),
13402
+ gapGptCatalogModel(AXMAiModelStableIds.gapGptGpt52, 'gpt-5.2', 'GPT-5.2 (GapGPT)', 'GPT-5.2 (گپ‌جی‌پی‌تی)', ['chat', 'vision'], { inputPricePerMillion: 1.75, outputPricePerMillion: 14, cachedInputPricePerMillion: 0.18 }),
13403
+ gapGptCatalogModel(AXMAiModelStableIds.gapGptGpt52ChatLatest, 'gpt-5.2-chat-latest', 'GPT-5.2 Chat Latest (GapGPT)', 'GPT-5.2 Chat Latest (گپ‌جی‌پی‌تی)', ['chat', 'vision'], { inputPricePerMillion: 1.75, outputPricePerMillion: 14 }),
13404
+ gapGptCatalogModel(AXMAiModelStableIds.gapGptGpt52Codex, 'gpt-5.2-codex', 'GPT-5.2 Codex (GapGPT)', 'GPT-5.2 Codex (گپ‌جی‌پی‌تی)', ['chat', 'vision'], { inputPricePerMillion: 1.75, outputPricePerMillion: 14 }),
13405
+ gapGptCatalogModel(AXMAiModelStableIds.gapGptGpt52Pro, 'gpt-5.2-pro', 'GPT-5.2 Pro (GapGPT)', 'GPT-5.2 Pro (گپ‌جی‌پی‌تی)', ['chat', 'vision'], { inputPricePerMillion: 21, outputPricePerMillion: 168 }),
13406
+ gapGptCatalogModel(AXMAiModelStableIds.gapGptGpt53ChatLatest, 'gpt-5.3-chat-latest', 'GPT-5.3 Chat Latest (GapGPT)', 'GPT-5.3 Chat Latest (گپ‌جی‌پی‌تی)', ['chat', 'vision'], { inputPricePerMillion: 1.75, outputPricePerMillion: 14 }),
13407
+ gapGptCatalogModel(AXMAiModelStableIds.gapGptGpt53Codex, 'gpt-5.3-codex', 'GPT-5.3 Codex (GapGPT)', 'GPT-5.3 Codex (گپ‌جی‌پی‌تی)', ['chat', 'vision'], { inputPricePerMillion: 1.75, outputPricePerMillion: 14, cachedInputPricePerMillion: 0.18 }),
13408
+ gapGptCatalogModel(AXMAiModelStableIds.gapGptGpt53CodexSpark, 'gpt-5.3-codex-spark', 'GPT-5.3 Codex Spark (GapGPT)', 'GPT-5.3 Codex Spark (گپ‌جی‌پی‌تی)', ['chat', 'vision'], { inputPricePerMillion: 1.75, outputPricePerMillion: 14, cachedInputPricePerMillion: 0.18 }),
13409
+ gapGptCatalogModel(AXMAiModelStableIds.gapGptClaudeOpus41, 'claude-opus-4-1-20250805', 'Claude Opus 4.1 (GapGPT)', 'Claude Opus 4.1 (گپ‌جی‌پی‌تی)', ['chat', 'vision'], { inputPricePerMillion: 15, outputPricePerMillion: 75 }),
13410
+ gapGptCatalogModel(AXMAiModelStableIds.gapGptClaudeOpus4, 'claude-opus-4-20250514', 'Claude Opus 4 (GapGPT)', 'Claude Opus 4 (گپ‌جی‌پی‌تی)', ['chat', 'vision'], { inputPricePerMillion: 15, outputPricePerMillion: 75 }),
13411
+ gapGptCatalogModel(AXMAiModelStableIds.gapGptClaudeOpus45, 'claude-opus-4-5-20251101', 'Claude Opus 4.5 (GapGPT)', 'Claude Opus 4.5 (گپ‌جی‌پی‌تی)', ['chat', 'vision'], { inputPricePerMillion: 5, outputPricePerMillion: 25 }),
13412
+ gapGptCatalogModel(AXMAiModelStableIds.gapGptZImage, 'gapgpt/z-image', 'Z-Image (GapGPT)', 'Z-Image (گپ‌جی‌پی‌تی)', ['image'], { inputPricePerMillion: 0.005 }),
13413
+ gapGptCatalogModel(AXMAiModelStableIds.gapGptGptImage2, 'gpt-image-2', 'GPT Image 2 (GapGPT)', 'GPT Image 2 (گپ‌جی‌پی‌تی)', ['image'], { inputPricePerMillion: 8, outputPricePerMillion: 30 }),
13414
+ gapGptCatalogModel(AXMAiModelStableIds.gapGptGemini3ProImagePreview, 'gemini-3-pro-image-preview', 'Gemini 3 Pro Image Preview (GapGPT)', 'Gemini 3 Pro Image Preview (گپ‌جی‌پی‌تی)', ['image'], { inputPricePerMillion: 2, outputPricePerMillion: 120 }),
13415
+ gapGptCatalogModel(AXMAiModelStableIds.gapGptGptImage1Mini, 'gpt-image-1-mini', 'GPT Image 1 Mini (GapGPT)', 'GPT Image 1 Mini (گپ‌جی‌پی‌تی)', ['image'], { inputPricePerMillion: 2, outputPricePerMillion: 4 }),
13416
+ gapGptCatalogModel(AXMAiModelStableIds.gapGptDalle3, 'dall-e-3', 'DALL·E 3 (GapGPT)', 'DALL·E 3 (گپ‌جی‌پی‌تی)', ['image'], { inputPricePerMillion: 0.04 }),
13417
+ gapGptCatalogModel(AXMAiModelStableIds.gapGptGemini25FlashImage, 'gemini-2.5-flash-image', 'Gemini 2.5 Flash Image (GapGPT)', 'Gemini 2.5 Flash Image (گپ‌جی‌پی‌تی)', ['image'], { inputPricePerMillion: 0.04 }),
13418
+ gapGptCatalogModel(AXMAiModelStableIds.gapGptGemini31FlashImagePreview, 'gemini-3.1-flash-image-preview', 'Gemini 3.1 Flash Image Preview (GapGPT)', 'Gemini 3.1 Flash Image Preview (گپ‌جی‌پی‌تی)', ['image'], { inputPricePerMillion: 0.08 }),
13419
+ gapGptCatalogModel(AXMAiModelStableIds.gapGptImagen40Fast, 'imagen-4.0-fast-generate-001', 'Imagen 4.0 Fast (GapGPT)', 'Imagen 4.0 Fast (گپ‌جی‌پی‌تی)', ['image'], { inputPricePerMillion: 0.02 }),
13420
+ gapGptCatalogModel(AXMAiModelStableIds.gapGptImagen40Ultra, 'imagen-4.0-ultra-generate-001', 'Imagen 4.0 Ultra (GapGPT)', 'Imagen 4.0 Ultra (گپ‌جی‌پی‌تی)', ['image'], { inputPricePerMillion: 0.06 }),
13421
+ gapGptCatalogModel(AXMAiModelStableIds.gapGptWhisper1, 'gapgpt/whisper-1', 'Whisper 1 hosted (GapGPT)', 'Whisper 1 میزبانی‌شده (گپ‌جی‌پی‌تی)', ['speech'], { inputPricePerMillion: 24, outputPricePerMillion: 24 }),
13422
+ gapGptCatalogModel(AXMAiModelStableIds.gapGptOpenAiWhisper1, 'whisper-1', 'Whisper 1 (GapGPT)', 'Whisper 1 (گپ‌جی‌پی‌تی)', ['speech'], { inputPricePerMillion: 30, outputPricePerMillion: 30 }),
13423
+ gapGptCatalogModel(AXMAiModelStableIds.gapGptGpt4oMiniTts, 'gpt-4o-mini-tts', 'GPT-4o Mini TTS (GapGPT)', 'GPT-4o Mini TTS (گپ‌جی‌پی‌تی)', ['tts'], { inputPricePerMillion: 0.6, outputPricePerMillion: 2.4 }),
13424
+ gapGptCatalogModel(AXMAiModelStableIds.gapGptTts1, 'tts-1', 'TTS-1 (GapGPT)', 'TTS-1 (گپ‌جی‌پی‌تی)', ['tts'], { inputPricePerMillion: 15, outputPricePerMillion: 15 }),
13425
+ gapGptCatalogModel(AXMAiModelStableIds.gapGptGemini25FlashPreviewTts, 'gemini-2.5-flash-preview-tts', 'Gemini 2.5 Flash Preview TTS (GapGPT)', 'Gemini 2.5 Flash Preview TTS (گپ‌جی‌پی‌تی)', ['tts'], { inputPricePerMillion: 0.5, outputPricePerMillion: 10 }),
13426
+ gapGptCatalogModel(AXMAiModelStableIds.gapGptGemini25ProPreviewTts, 'gemini-2.5-pro-preview-tts', 'Gemini 2.5 Pro Preview TTS (GapGPT)', 'Gemini 2.5 Pro Preview TTS (گپ‌جی‌پی‌تی)', ['tts'], { inputPricePerMillion: 2, outputPricePerMillion: 40 }),
13427
+ gapGptCatalogModel(AXMAiModelStableIds.gapGptGemma327bIt, 'gemma-3-27b-it', 'Gemma 3 27B IT (GapGPT)', 'Gemma 3 27B IT (گپ‌جی‌پی‌تی)', ['chat', 'vision'], { inputPricePerMillion: 0.013, outputPricePerMillion: 0.05 }),
13428
+ gapGptCatalogModel(AXMAiModelStableIds.gapGptDeepseekV4Flash, 'deepseek-v4-flash', 'DeepSeek V4 Flash (GapGPT)', 'DeepSeek V4 Flash (گپ‌جی‌پی‌تی)', ['chat', 'vision'], { inputPricePerMillion: 0.28, outputPricePerMillion: 0.078 }),
13429
+ gapGptCatalogModel(AXMAiModelStableIds.gapGptGemini25FlashLite, 'gemini-2.5-flash-lite', 'Gemini 2.5 Flash Lite (GapGPT)', 'Gemini 2.5 Flash Lite (گپ‌جی‌پی‌تی)', ['chat', 'vision'], { inputPricePerMillion: 0.1, outputPricePerMillion: 0.4 }),
13430
+ gapGptCatalogModel(AXMAiModelStableIds.gapGptGpt41Nano, 'gpt-4.1-nano', 'GPT-4.1 Nano (GapGPT)', 'GPT-4.1 Nano (گپ‌جی‌پی‌تی)', ['chat', 'vision'], { inputPricePerMillion: 0.1, outputPricePerMillion: 0.4, cachedInputPricePerMillion: 0.025 }),
13431
+ gapGptCatalogModel(AXMAiModelStableIds.gapGptGpt5Nano, 'gpt-5-nano', 'GPT-5 Nano (GapGPT)', 'GPT-5 Nano (گپ‌جی‌پی‌تی)', ['chat', 'vision'], { inputPricePerMillion: 0.05, outputPricePerMillion: 0.4 }),
13432
+ gapGptCatalogModel(AXMAiModelStableIds.gapGptQwen3235bA22b, 'qwen3-235b-a22b', 'Qwen3 235B A22B (GapGPT)', 'Qwen3 235B A22B (گپ‌جی‌پی‌تی)', ['chat', 'vision'], { inputPricePerMillion: 0.16, outputPricePerMillion: 0.48 }),
13433
+ gapGptCatalogModel(AXMAiModelStableIds.gapGptGpt4oMini, 'gpt-4o-mini', 'GPT-4o Mini (GapGPT)', 'GPT-4o Mini (گپ‌جی‌پی‌تی)', ['chat', 'vision'], { inputPricePerMillion: 0.15, outputPricePerMillion: 0.6, cachedInputPricePerMillion: 0.075 }),
13434
+ gapGptCatalogModel(AXMAiModelStableIds.gapGptGemini31FlashLitePreview, 'gemini-3.1-flash-lite-preview', 'Gemini 3.1 Flash Lite Preview (GapGPT)', 'Gemini 3.1 Flash Lite Preview (گپ‌جی‌پی‌تی)', ['chat', 'vision'], { inputPricePerMillion: 0.25, outputPricePerMillion: 1.5 }),
13435
+ gapGptCatalogModel(AXMAiModelStableIds.gapGptGeminiFlashLiteLatest, 'gemini-flash-lite-latest', 'Gemini Flash Lite Latest (GapGPT)', 'Gemini Flash Lite Latest (گپ‌جی‌پی‌تی)', ['chat', 'vision'], { inputPricePerMillion: 0.25, outputPricePerMillion: 1.5 }),
13436
+ gapGptCatalogModel(AXMAiModelStableIds.gapGptGrok3Mini, 'grok-3-mini', 'Grok 3 Mini (GapGPT)', 'Grok 3 Mini (گپ‌جی‌پی‌تی)', ['chat', 'vision'], { inputPricePerMillion: 0.3, outputPricePerMillion: 1.5 }),
13437
+ gapGptCatalogModel(AXMAiModelStableIds.gapGptGpt41Mini, 'gpt-4.1-mini', 'GPT-4.1 Mini (GapGPT)', 'GPT-4.1 Mini (گپ‌جی‌پی‌تی)', ['chat', 'vision'], { inputPricePerMillion: 0.4, outputPricePerMillion: 1.6, cachedInputPricePerMillion: 0.1 }),
13438
+ ];
13439
+ //#endregion
13440
+ //#region ---- Gemini API catalog helpers ----
13441
+ const GEMINI_DEFAULT_CONTEXT = {
13442
+ maxContextTokens: 1_048_576,
13443
+ maxOutputTokens: 65_536,
13444
+ maxInputTokens: 1_032_192,
13445
+ };
13446
+ /**
13447
+ * Builds a Google Gemini API catalog row (USD per 1M tokens; Standard tier, ≤200K context).
13448
+ */
13449
+ function geminiApiCatalogModel(id, name, titleEn, titleFa, modelPurposes, pricing, context = GEMINI_DEFAULT_CONTEXT) {
13450
+ return {
13451
+ id,
13452
+ name,
13453
+ title: M$1c(titleEn, titleFa),
13454
+ description: M$1c(`Gemini API: ${name}`, `API جمینای: ${name}`),
13455
+ chatTransport: 'gemini',
13456
+ modelPurposes,
13457
+ ...context,
13458
+ ...pricing,
13459
+ };
13460
+ }
13461
+ /** Direct Gemini API models (excludes rows already defined in {@link AI_MODEL_MOCK} seed). */
13462
+ const GEMINI_API_CATALOG_MOCK = [
13463
+ geminiApiCatalogModel(AXMAiModelStableIds.gemini25Pro, 'gemini-2.5-pro', 'Gemini 2.5 Pro', 'جمینای ۲٫۵ پرو', ['chat', 'vision', 'speech'], { inputPricePerMillion: 1.25, outputPricePerMillion: 10, cachedInputPricePerMillion: 0.13 }),
13464
+ geminiApiCatalogModel(AXMAiModelStableIds.gemini25FlashLite, 'gemini-2.5-flash-lite', 'Gemini 2.5 Flash Lite', 'جمینای ۲٫۵ فلش لایت', ['chat', 'vision', 'speech'], { inputPricePerMillion: 0.1, outputPricePerMillion: 0.4, cachedInputPricePerMillion: 0.01 }),
13465
+ geminiApiCatalogModel(AXMAiModelStableIds.gemini35Flash, 'gemini-3.5-flash', 'Gemini 3.5 Flash', 'جمینای ۳٫۵ فلش', ['chat', 'vision', 'speech'], { inputPricePerMillion: 1.5, outputPricePerMillion: 9, cachedInputPricePerMillion: 0.15 }),
13466
+ geminiApiCatalogModel(AXMAiModelStableIds.gemini31ProPreview, 'gemini-3.1-pro-preview', 'Gemini 3.1 Pro Preview', 'جمینای ۳٫۱ پرو (پیش‌نمایش)', ['chat', 'vision', 'speech'], { inputPricePerMillion: 2, outputPricePerMillion: 12, cachedInputPricePerMillion: 0.2 }),
13467
+ geminiApiCatalogModel(AXMAiModelStableIds.gemini3FlashPreview, 'gemini-3-flash-preview', 'Gemini 3 Flash Preview', 'جمینای ۳ فلش (پیش‌نمایش)', ['chat', 'vision', 'speech'], { inputPricePerMillion: 0.5, outputPricePerMillion: 3, cachedInputPricePerMillion: 0.05 }),
13468
+ geminiApiCatalogModel(AXMAiModelStableIds.gemini31FlashLite, 'gemini-3.1-flash-lite', 'Gemini 3.1 Flash Lite', 'جمینای ۳٫۱ فلش لایت', ['chat', 'vision', 'speech'], { inputPricePerMillion: 0.25, outputPricePerMillion: 1.5, cachedInputPricePerMillion: 0.025 }),
13469
+ geminiApiCatalogModel(AXMAiModelStableIds.gemini25FlashImage, 'gemini-2.5-flash-image', 'Gemini 2.5 Flash Image', 'جمینای ۲٫۵ فلش تصویر', ['image'], { inputPricePerMillion: 0.3, outputPricePerMillion: 30 }, { maxContextTokens: 32_768, maxOutputTokens: 8_192, maxInputTokens: 32_768 }),
13470
+ geminiApiCatalogModel(AXMAiModelStableIds.gemini3ProImagePreview, 'gemini-3-pro-image-preview', 'Gemini 3 Pro Image Preview', 'جمینای ۳ پرو تصویر (پیش‌نمایش)', ['image'], { inputPricePerMillion: 2, outputPricePerMillion: 120 }, { maxContextTokens: 32_768, maxOutputTokens: 8_192, maxInputTokens: 32_768 }),
13471
+ geminiApiCatalogModel(AXMAiModelStableIds.gemini31FlashImagePreview, 'gemini-3.1-flash-image-preview', 'Gemini 3.1 Flash Image Preview', 'جمینای ۳٫۱ فلش تصویر (پیش‌نمایش)', ['image'], { inputPricePerMillion: 0.5, outputPricePerMillion: 60 }, { maxContextTokens: 32_768, maxOutputTokens: 8_192, maxInputTokens: 32_768 }),
13472
+ geminiApiCatalogModel(AXMAiModelStableIds.imagen40FastGenerate001, 'imagen-4.0-fast-generate-001', 'Imagen 4.0 Fast', 'Imagen 4.0 Fast', ['image'], { inputPricePerMillion: 0.02 }, { maxContextTokens: 480, maxOutputTokens: 480, maxInputTokens: 480 }),
13473
+ geminiApiCatalogModel(AXMAiModelStableIds.imagen40UltraGenerate001, 'imagen-4.0-ultra-generate-001', 'Imagen 4.0 Ultra', 'Imagen 4.0 Ultra', ['image'], { inputPricePerMillion: 0.06 }, { maxContextTokens: 480, maxOutputTokens: 480, maxInputTokens: 480 }),
13474
+ geminiApiCatalogModel(AXMAiModelStableIds.gemini25FlashPreviewTts, 'gemini-2.5-flash-preview-tts', 'Gemini 2.5 Flash Preview TTS', 'جمینای ۲٫۵ فلش TTS (پیش‌نمایش)', ['tts'], { inputPricePerMillion: 0.5, outputPricePerMillion: 10 }),
13475
+ geminiApiCatalogModel(AXMAiModelStableIds.gemini25ProPreviewTts, 'gemini-2.5-pro-preview-tts', 'Gemini 2.5 Pro Preview TTS', 'جمینای ۲٫۵ پرو TTS (پیش‌نمایش)', ['tts'], { inputPricePerMillion: 2, outputPricePerMillion: 40 }),
13476
+ ];
13477
+ //#endregion
13271
13478
  //#region ---- Default AI Models ----
13272
13479
  const AI_MODEL_MOCK = [
13273
13480
  {
@@ -13284,6 +13491,7 @@ const AI_MODEL_MOCK = [
13284
13491
  outputPricePerMillion: 2.5,
13285
13492
  cachedInputPricePerMillion: 0.03,
13286
13493
  },
13494
+ ...GEMINI_API_CATALOG_MOCK,
13287
13495
  {
13288
13496
  id: AXMAiModelStableIds.gpt54,
13289
13497
  name: 'gpt-5.4',
@@ -13347,6 +13555,7 @@ const AI_MODEL_MOCK = [
13347
13555
  description: M$1c('Text-to-image via Gemini API predict endpoint (paid tier; English prompts per Google docs)', 'متن‌به‌تصویر از طریق endpoint پیش‌بینی Gemini API (لایه پولی؛ پرامپت انگلیسی طبق مستندات گوگل)'),
13348
13556
  chatTransport: 'gemini',
13349
13557
  modelPurposes: ['image'],
13558
+ inputPricePerMillion: 0.04,
13350
13559
  },
13351
13560
  {
13352
13561
  id: AXMAiModelStableIds.openaiGptImage1,
@@ -13378,6 +13587,32 @@ const AI_MODEL_MOCK = [
13378
13587
  openAiEndpoint: mockOpenAiEndpointSnapshot(AXMAiOpenAiEndpointStableIds.openAiDirect),
13379
13588
  modelPurposes: ['tts'],
13380
13589
  },
13590
+ {
13591
+ id: AXMAiModelStableIds.openrouterOwlAlpha,
13592
+ name: 'openrouter/owl-alpha',
13593
+ title: M$1c('OpenRouter Owl Alpha', 'OpenRouter Owl Alpha'),
13594
+ description: M$1c('OpenRouter model catalog row: openrouter/owl-alpha', 'ردیف کاتالوگ OpenRouter: openrouter/owl-alpha'),
13595
+ chatTransport: 'openai',
13596
+ openAiEndpointId: AXMAiOpenAiEndpointStableIds.openRouter,
13597
+ openAiEndpoint: mockOpenAiEndpointSnapshot(AXMAiOpenAiEndpointStableIds.openRouter),
13598
+ modelPurposes: ['chat'],
13599
+ inputPricePerMillion: 0,
13600
+ outputPricePerMillion: 0,
13601
+ cachedInputPricePerMillion: 0,
13602
+ },
13603
+ {
13604
+ id: AXMAiModelStableIds.openrouterQwen3Next80bA3bInstructFree,
13605
+ name: 'qwen/qwen3-next-80b-a3b-instruct:free',
13606
+ title: M$1c('Qwen3 Next 80B A3B Instruct (Free)', 'Qwen3 Next 80B A3B Instruct (رایگان)'),
13607
+ description: M$1c('OpenRouter model catalog row: qwen/qwen3-next-80b-a3b-instruct:free', 'ردیف کاتالوگ OpenRouter: qwen/qwen3-next-80b-a3b-instruct:free'),
13608
+ chatTransport: 'openai',
13609
+ openAiEndpointId: AXMAiOpenAiEndpointStableIds.openRouter,
13610
+ openAiEndpoint: mockOpenAiEndpointSnapshot(AXMAiOpenAiEndpointStableIds.openRouter),
13611
+ modelPurposes: ['chat'],
13612
+ inputPricePerMillion: 0,
13613
+ outputPricePerMillion: 0,
13614
+ cachedInputPricePerMillion: 0,
13615
+ },
13381
13616
  {
13382
13617
  id: AXMAiModelStableIds.lmStudioQwen35_9b,
13383
13618
  name: 'qwen/qwen3.5-9b',
@@ -13450,6 +13685,7 @@ const AI_MODEL_MOCK = [
13450
13685
  isDisabled: true,
13451
13686
  openAiEndpointIsDisabled: true,
13452
13687
  },
13688
+ ...GAP_GPT_PRICING_CATALOG_MOCK,
13453
13689
  ];
13454
13690
  //#endregion
13455
13691
 
@@ -13470,113 +13706,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
13470
13706
  type: Injectable
13471
13707
  }] });
13472
13708
 
13473
- //#region ---- Imports ----
13474
- //#endregion
13475
- const M$1b = createMultiLanguageString;
13476
- //#region ---- Stable ids ----
13477
- const AXMAiRuleMarkdownId = 'd0000001-0000-4000-8000-000000000001';
13478
- /** Programmatic rule name for user-visible Markdown formatting. */
13479
- const AXMAiRuleMarkdownName = 'markdown';
13480
- const AXMAiRuleWorkflowNarrationId = 'd0000002-0000-4000-8000-000000000002';
13481
- /** Programmatic rule name for brief before/after step narration in conversation chat. */
13482
- const AXMAiRuleWorkflowNarrationName = 'workflow-narration';
13483
- const AXMAiRuleEndUserLanguageId = 'd0000003-0000-4000-8000-000000000003';
13484
- /** Programmatic rule name for non-technical, end-user-friendly assistant copy in conversation chat. */
13485
- const AXMAiRuleEndUserLanguageName = 'end-user-language';
13486
- //#endregion
13487
- //#region ---- Default markdown rule body ----
13488
- /** Former {@link AXC_AI_ASSIST_SYSTEM_PROMPT} baseline — now catalog-managed. */
13489
- const AXC_AI_MARKDOWN_RULE_BODY = [
13490
- '## Response format (user-visible text)',
13491
- '- **Always use Markdown** in plain-text replies to the user (not in tool JSON). Prefer rich structure over flat paragraphs.',
13492
- '- **Headings**: use `##` / `###` to separate topics; keep a short lead line under each heading.',
13493
- '- **Emphasis**: use **bold** for key terms, numbers, names, and conclusions; use *italic* sparingly for nuance.',
13494
- '- **Lists**: use bullet lists for unordered items and numbered lists for steps, rankings, or sequences.',
13495
- '- **Tables**: use Markdown tables when comparing columns or showing multiple entities with the same fields.',
13496
- '- **Code**: wrap identifiers, paths, keys, and short snippets in `inline code`; use fenced code blocks only when showing multi-line examples.',
13497
- '- **Links**: use `[label](url)` when citing URLs; do not paste bare long URLs without a label.',
13498
- '- **Density**: break long answers into scannable sections; avoid walls of text — one idea per bullet when listing facts.',
13499
- '- **Charts / layout envelopes**: when the UI renders structured output, still add a brief Markdown summary (bullets + **bold** highlights) above or beside it.',
13500
- ].join('\n');
13501
- /** Conversation assist: short progress beats before/after tools and delegated agents. */
13502
- const AXC_AI_WORKFLOW_NARRATION_RULE_BODY = [
13503
- '## Workflow narration (keep the user in the loop)',
13504
- '- For **multi-step** work (platform lookup, delegated specialists, mutations, layout builds), narrate progress in **user-visible** assistant text — not inside tool JSON.',
13505
- '- **Before** each substantive step (tool call or delegated specialist): **1–2 short sentences** in **plain language** — what you will do next (e.g. “Let me find where user registration is in the app.”).',
13506
- '- **After** each step returns: **1–2 short sentences** — what you learned in user terms, then what you will do next (e.g. “I found the registration screen fields. Next I’ll draft the form layout.”).',
13507
- '- Match the user’s language (Persian or English). Use Markdown from the `markdown` rule for structure.',
13508
- '- Keep each beat **brief**; narration is for orientation, not long essays. Skip narration only for trivial one-line replies (greetings, thanks, single fact with no tools).',
13509
- '- Do **not** repeat the same beat twice. Do **not** hide tool/agent work — the user should be able to follow the thread without reading raw tool payloads.',
13510
- '',
13511
- '### Example (user: “Build a user registration form”)',
13512
- '1. *Before lookup:* “I’ll check how user registration is set up in the app.”',
13513
- '2. *After lookup:* “I found the registration fields — next I’ll build the form layout.”',
13514
- '3. *After layout:* “Here is the registration form …” (then deliver the layout / summary as usual).',
13515
- ].join('\n');
13516
- /** Conversation assist: plain language for non-technical end users. */
13517
- const AXC_AI_END_USER_LANGUAGE_RULE_BODY = [
13518
- '## End-user language (no technical jargon)',
13519
- '- The reader is an **end user**, not a developer or admin. Write as a helpful product guide, not an internal runbook.',
13520
- '- **Never** expose in user-visible text: module names, `Module.Entity` keys, registry/command/query names, agent or specialist ids, `fileId`, UUIDs, JSON tool payloads, chart/widget construction steps, datasource names, or “how the platform built” something.',
13521
- '- **Navigation**: describe where to click using **menu labels and breadcrumbs** the user sees — not internal entity keys or API identifiers.',
13522
- '- **Charts / forms / layouts**: show the result (chart, form, image) via structured UI segments when available; summarize in plain language (“Here is the sales chart for last month.”) — do not explain widget trees, block-layout, or validation commands.',
13523
- '- **Images / files**: the UI renders them automatically. Confirm with one short sentence only; do not paste file metadata or JSON.',
13524
- '- **When something fails**: one clear sentence in everyday language and what the user can try next — no stack traces, error codes, or tool names unless the user explicitly asks for technical detail.',
13525
- '- Match the user’s language (Persian or English). Keep Markdown from the `markdown` rule when it helps scannability.',
13526
- ].join('\n');
13527
- //#endregion
13528
- //#region ---- Mock helpers ----
13529
- /** Builds multi-lookup storage (`ruleIds` + denormalized `rules`) for assist/agent mocks. */
13530
- function axcAiRuleRefsByIds(...ids) {
13531
- const rules = [];
13532
- for (const raw of ids) {
13533
- const id = raw.trim();
13534
- if (!id) {
13535
- continue;
13536
- }
13537
- const row = AI_RULE_MOCK.find((r) => r.id === id);
13538
- if (!row) {
13539
- continue;
13540
- }
13541
- rules.push({ id: row.id, name: row.name, title: row.title });
13542
- }
13543
- return { ruleIds: rules.map((r) => r.id), rules };
13544
- }
13545
- /** Mock helper: resolve catalog rows by programmatic `name`, persist as `ruleIds`. */
13546
- function axcAiRuleRefsByNames(...names) {
13547
- const ids = names
13548
- .map((n) => n.trim())
13549
- .map((name) => AI_RULE_MOCK.find((r) => r.name === name)?.id)
13550
- .filter((id) => !!id);
13551
- return axcAiRuleRefsByIds(...ids);
13552
- }
13553
- //#endregion
13554
- //#region ---- Mock rows ----
13555
- const AI_RULE_MOCK = [
13556
- {
13557
- id: AXMAiRuleMarkdownId,
13558
- name: AXMAiRuleMarkdownName,
13559
- title: M$1b('Markdown replies', 'پاسخ‌های Markdown'),
13560
- description: M$1b('Format user-visible assistant text with headings, lists, tables, and emphasis.', 'قالب‌بندی متن قابل‌مشاهده برای کاربر با عنوان، فهرست، جدول و تأکید.'),
13561
- markdown: AXC_AI_MARKDOWN_RULE_BODY,
13562
- },
13563
- {
13564
- id: AXMAiRuleWorkflowNarrationId,
13565
- name: AXMAiRuleWorkflowNarrationName,
13566
- title: M$1b('Workflow narration', 'روایت گام‌های کار'),
13567
- description: M$1b('Brief before/after explanations for each tool or specialist step so the user can follow progress.', 'توضیح کوتاه قبل و بعد از هر ابزار یا متخصص تا کاربر روند کار را دنبال کند.'),
13568
- markdown: AXC_AI_WORKFLOW_NARRATION_RULE_BODY,
13569
- },
13570
- {
13571
- id: AXMAiRuleEndUserLanguageId,
13572
- name: AXMAiRuleEndUserLanguageName,
13573
- title: M$1b('End-user language', 'زبان کاربر نهایی'),
13574
- description: M$1b('Plain, non-technical replies for conversation chat — no module names, tool ids, or implementation details.', 'پاسخ ساده و غیرفنی در چت مکالمه — بدون نام ماژول، شناسه ابزار یا جزئیات پیاده‌سازی.'),
13575
- markdown: AXC_AI_END_USER_LANGUAGE_RULE_BODY,
13576
- },
13577
- ];
13578
- //#endregion
13579
-
13580
13709
  //#region ---- Imports ----
13581
13710
  //#endregion
13582
13711
  //#region ---- Lookup caches ----
@@ -13677,7 +13806,7 @@ const AXM_AI_REGISTRY_QUERY_NAME = {
13677
13806
 
13678
13807
  //#region ---- Imports ----
13679
13808
  //#endregion
13680
- const M$1a = createMultiLanguageString;
13809
+ const M$1b = createMultiLanguageString;
13681
13810
  //#region ---- Helpers ----
13682
13811
  function aiAgentCommandBinding(registryId, options = {}) {
13683
13812
  return {
@@ -13695,6 +13824,15 @@ function aiAgentQueryBinding(registryId, options = {}) {
13695
13824
  },
13696
13825
  };
13697
13826
  }
13827
+ /** Supervisor routing fields for delegated `agent:<id>` tool descriptions (plain English for the LLM). */
13828
+ function supervisorRouting(opts) {
13829
+ return {
13830
+ supervisorWhenToUse: opts.whenToUse.trim(),
13831
+ supervisorWhenNotToUse: opts.whenNotToUse.trim(),
13832
+ ...(opts.chainsWith?.trim() ? { supervisorChainsWith: opts.chainsWith.trim() } : {}),
13833
+ ...(opts.tags?.length ? { supervisorIntentTags: [...opts.tags] } : {}),
13834
+ };
13835
+ }
13698
13836
  //#endregion
13699
13837
  //#region ---- Shared parameter groups ----
13700
13838
  const SUPERVISOR_GROUP = { name: 'supervisor-params', title: 'Supervisor', order: 1 };
@@ -13748,6 +13886,23 @@ const SPEECH_TO_TEXT_PARAMETER_DEFINITIONS = [
13748
13886
  title: 'Speech model',
13749
13887
  description: 'AiModel catalog row id (purpose: speech). Set per assist on this delegated specialist row; the supervisor may override by passing model in the tool call.',
13750
13888
  group: ASSIST_GROUP,
13889
+ defaultValue: AXMAiModelStableIds.openaiWhisper1,
13890
+ interface: {
13891
+ name: 'lookup-editor',
13892
+ options: {
13893
+ entity: 'AiManagement.AiModel',
13894
+ textField: 'title',
13895
+ valueField: 'id',
13896
+ look: 'select',
13897
+ allowSearch: true,
13898
+ columns: ['title', 'name'],
13899
+ filter: {
13900
+ field: 'modelPurposes',
13901
+ operator: { type: 'contains' },
13902
+ value: 'speech',
13903
+ },
13904
+ },
13905
+ },
13751
13906
  },
13752
13907
  {
13753
13908
  name: 'language',
@@ -13771,6 +13926,23 @@ const TEXT_TO_SPEECH_PARAMETER_DEFINITIONS = [
13771
13926
  title: 'TTS model',
13772
13927
  description: 'AiModel catalog row id (purpose: tts). Set per assist on this delegated specialist row; the supervisor may override by passing model.',
13773
13928
  group: ASSIST_GROUP,
13929
+ defaultValue: AXMAiModelStableIds.openaiTts1,
13930
+ interface: {
13931
+ name: 'lookup-editor',
13932
+ options: {
13933
+ entity: 'AiManagement.AiModel',
13934
+ textField: 'title',
13935
+ valueField: 'id',
13936
+ look: 'select',
13937
+ allowSearch: true,
13938
+ columns: ['title', 'name'],
13939
+ filter: {
13940
+ field: 'modelPurposes',
13941
+ operator: { type: 'contains' },
13942
+ value: 'tts',
13943
+ },
13944
+ },
13945
+ },
13774
13946
  },
13775
13947
  {
13776
13948
  name: 'voice',
@@ -13806,8 +13978,14 @@ const AI_AGENT_MOCK = [
13806
13978
  {
13807
13979
  id: AXMAiAgentPlatformHelpId,
13808
13980
  name: 'platform-help',
13809
- title: M$1a('Platform Help and Navigation', 'راهنمای پلتفرم و ناوبری'),
13810
- description: M$1a('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** را واگذار می‌کند.'),
13981
+ title: M$1b('Platform Help and Navigation', 'راهنمای پلتفرم و ناوبری'),
13982
+ description: M$1b('App navigation and menu discovery specialist (read-only).', 'متخصص ناوبری اپ و کشف منو (فقط خواندنی).'),
13983
+ ...supervisorRouting({
13984
+ whenToUse: 'Delegate when the user needs **how to use the app**: where a feature is in menus/sidebar, onboarding steps, which screen to open, or which Module.Entity backs a page — **without** listing or changing stored records.',
13985
+ whenNotToUse: 'Do NOT delegate for querying/counting/aggregating **stored rows**, create/update/delete, charts, forms/tables in chat, images, audio, or OCR — use **platform-entity**, **widget-chart-layout**, **widget-form-layout**, or media specialists.',
13986
+ chainsWith: 'After navigation/catalog answers, chain **platform-entity** when the user needs real data, filters, or mutations.',
13987
+ tags: ['navigation', 'menu', 'onboarding', 'help'],
13988
+ }),
13811
13989
  commandIds: [],
13812
13990
  queryIds: [
13813
13991
  aiAgentQueryBinding(axcResolveQueryRegistrySeedId(AXM_AI_REGISTRY_QUERY_NAME.listPlatformNavigationForAi)),
@@ -13847,8 +14025,13 @@ const AI_AGENT_MOCK = [
13847
14025
  {
13848
14026
  id: AXMAiAgentWidgetFollowUpChipsLayoutId,
13849
14027
  name: 'follow-up-prompt-generator',
13850
- title: M$1a('Follow-Up Suggestions Agent', 'دستیار پیشنهادهای بعدی'),
13851
- description: M$1a('Reads conversation context and proposes next-step chips for Conversation assist. No registry commands or queries.', 'با توجه به زمینهٔ مکالمه پیشنهاد گام بعدی برای دستیار مکالمه می‌سازد. بدون فرمان یا پرس‌وجوی رجیستری.'),
14028
+ title: M$1b('Follow-Up Suggestions Agent', 'دستیار پیشنهادهای بعدی'),
14029
+ description: M$1b('End-of-turn follow-up suggestion chips (structured followUp segment).', 'تراشه‌های پیشنهاد گام بعدی در پایان نوبت (سگمنت followUp).'),
14030
+ ...supervisorRouting({
14031
+ whenToUse: 'Delegate **last** in the turn after all domain specialists, when the exchange involved a real task (not greeting/thanks only). Pass conversation context in `query`.',
14032
+ whenNotToUse: 'Do NOT delegate as the first or only call for greetings, thanks, or single-fact replies with no follow-on work.',
14033
+ tags: ['follow-up', 'chips', 'end-of-turn'],
14034
+ }),
13852
14035
  commandIds: [],
13853
14036
  queryIds: [],
13854
14037
  outputContract: 'followUp',
@@ -13867,8 +14050,14 @@ const AI_AGENT_MOCK = [
13867
14050
  {
13868
14051
  id: AXMAiAgentPlatformEntityId,
13869
14052
  name: 'platform-entity',
13870
- title: M$1a('Platform Entity Agent', 'دستیار موجودیت پلتفرم'),
13871
- description: M$1a('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 the supervising assistant to present.', 'کار با موجودیت‌های پلتفرم: کشف کلیدهای Module.Entity و تعاریف فیلدها، فهرست یا جستجوی رکوردها، و ایجاد یا به‌روزرسانی از طریق دستورات استاندارد موجودیت. خروجی متن/JSON واقعی برای ارائه توسط دستیار سرپرست.'),
14053
+ title: M$1b('Platform Entity Agent', 'دستیار موجودیت پلتفرم'),
14054
+ description: M$1b('Platform data specialist: entity discovery, storage query, create/update.', 'متخصص داده پلتفرم: کشف موجودیت، کوئری ذخیره‌سازی، ایجاد/به‌روزرسانی.'),
14055
+ ...supervisorRouting({
14056
+ whenToUse: 'Delegate when the user needs **data from the system**: discover Module.Entity keys/schemas, **query/list/count/aggregate** stored rows, or **create/update** records. Finish pagination before summaries or hand-off to chart/layout specialists.',
14057
+ whenNotToUse: 'Do NOT delegate for pure “where is the menu” / onboarding without row operations — use **platform-help**. Do NOT build chat widget trees or charts here.',
14058
+ chainsWith: 'After factual rows exist, chain **widget-chart-layout** for charts or **widget-form-layout** for tables/forms/buttons — do not paste large markdown tables when a widget specialist will render.',
14059
+ tags: ['entity', 'crud', 'query', 'data'],
14060
+ }),
13872
14061
  commandIds: [
13873
14062
  aiAgentCommandBinding(axcResolveCommandRegistrySeedId(AXM_AI_REGISTRY_COMMAND_NAME.entityCreate)),
13874
14063
  aiAgentCommandBinding(axcResolveCommandRegistrySeedId(AXM_AI_REGISTRY_COMMAND_NAME.entityUpdate)),
@@ -13893,8 +14082,14 @@ const AI_AGENT_MOCK = [
13893
14082
  {
13894
14083
  id: AXMAiAgentWidgetFormLayoutId,
13895
14084
  name: 'widget-form-layout',
13896
- title: M$1a('Form Layout Agent', 'دستیار چیدمان فرم'),
13897
- description: M$1a('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`).', 'درخت ویجت پلتفرم برای فرم و UI چت؛ repeater-layout، select-editor با dataSource، lookup-editor با ListRegisteredEntities، و در نهایت text-editor. از Widgets:GetForAI با scope فرم استفاده می‌کند.'),
14085
+ title: M$1b('Form Layout Agent', 'دستیار چیدمان فرم'),
14086
+ description: M$1b('Chat UI via platform widgets: forms, buttons, tables (table-layout) not markdown tables.', 'رابط چت با ویجت پلتفرم: فرم، دکمه، جدول (table-layout) نه جدول markdown.'),
14087
+ ...supervisorRouting({
14088
+ whenToUse: 'Delegate when the user should **see** data as an interactive **form**, **button**, or **table-layout** in chat (including mini surveys and labeled inputs). Prefer this over long markdown bullet lists for similar records.',
14089
+ whenNotToUse: 'Do NOT delegate for charts (bar/line/donut/…) — **widget-chart-layout**. Do NOT duplicate: if this specialist returns a `node`, the supervisor must **not** also paste the same content as a markdown table.',
14090
+ chainsWith: 'Usually after **platform-entity** (or another data agent) supplies real row facts; pass those facts in `query`.',
14091
+ tags: ['form', 'table', 'layout', 'widget', 'button'],
14092
+ }),
13898
14093
  commandIds: [
13899
14094
  aiAgentCommandBinding(axcResolveCommandRegistrySeedId(AXM_AI_REGISTRY_COMMAND_NAME.aiFormbuilderValidateLayoutJsonForAi)),
13900
14095
  ],
@@ -13983,7 +14178,7 @@ const AI_AGENT_MOCK = [
13983
14178
  '',
13984
14179
  '## Widget registry pass (per data field — **text-editor** is last resort)',
13985
14180
  '- **Forbidden lazy pattern**: filling the form with **`text-editor`** for every column. For **each** input, decide semantics **first**, then set the leaf **`type`**.',
13986
- '- **Registry shortcuts** (names must match the catalog): **date / time / datetime** → **`date-time-editor`**. **Numeric** (count, year as number, money, measurement) → **`number-editor`**. **Closed set / lookup / category** → **`select-editor`** (or **`selection-list-editor`** for multi). **Long plain text** → **`large-text-editor`**. **Rich text** → **`rich-text-editor`**. **Boolean / consent** → **`checkbox-editor`** or **`toggle-editor`**. **Phone / email / contact** → **`contact-editor`** when appropriate. **Postal / structured address** → **`address-editor`**. **Map, pin, polygon, “روی نقشه”** → **`map`**, not a pair of lat/long **text-editor**s. **Uploads** → **`file-uploader`**. **Password** → **`password-editor`**. **Color** → **`color-editor`** / **`color-palette-editor`**. **Duration** → **`time-duration-editor`**. **Rating** → **`rate-picker`**. **Signature** → **`signature`**.',
14181
+ '- **Registry shortcuts** (names must match the catalog): **date / time / datetime** → **`date-time-editor`**. **Numeric** (count, year as number, money, measurement) → **`number-editor`**. **Closed set / lookup / category** → **`select-editor`** (or **`selection-list-editor`** for multi). **Long plain text** → **`large-text-editor`**. **Rich text** → **`rich-text-editor`**. **Boolean / consent** → **`checkbox-editor`** or **`toggle-editor`**. **Phone / email / contact** → **`contact-editor`** when appropriate. **Postal / structured address** → **`address-editor`**. **Map, pin, polygon, “روی نقشه”** → **`map`**, not a pair of lat/long **text-editor**s. **Uploads** → **`attachments`**. **Password** → **`password-editor`**. **Color** → **`color-editor`** / **`color-palette-editor`**. **Duration** → **`time-duration-editor`**. **Rating** → **`rate-picker`**. **Signature** → **`signature`**.',
13987
14182
  '- **Sizing in grids**: when using **`cols`**, **`grid-layout`**, or **`flex-item-layout`**, place **wide** editors (**`map`**, **`large-text-editor`**, **`address-editor`**) in **full-width** rows or wide cells; keep **short** fields in **half-width** columns so the form is not one column of identical text boxes.',
13988
14183
  '- **Strict fallback order**: (1) best semantic match; (2) if options are unknown, **GetForAI** for that widget name, then wire minimal valid **options**; (3) only if **no** catalog editor fits, use **`text-editor`** for unstructured single-line text.',
13989
14184
  '',
@@ -14013,7 +14208,7 @@ const AI_AGENT_MOCK = [
14013
14208
  '- **`date-time-editor`**: any field that is **logically a date or time** (see Field semantics pass).',
14014
14209
  '- **`select-editor`**: categorical choice, lookup, or data-bound list (see Field semantics pass); always discover **`options` / data source** with GetForAI — do not guess nested schema.',
14015
14210
  '- **`checkbox-editor` / `toggle-editor`**: binary flags; **`tag-editor`** only when tags/chips are appropriate per GetForAI.',
14016
- '- **`file-uploader`** / **`image`**: attachments, scans, photos when the user asks for uploads — discover with GetForAI.',
14211
+ '- **`attachments`** / **`image`**: attachments, scans, photos when the user asks for uploads — discover with GetForAI.',
14017
14212
  '- **`map`**: geographic selection, markers, polygons — not **`text-editor`** for lat/long unless explicitly requested.',
14018
14213
  '- **`address-editor`**: composite address capture when one structured value is intended.',
14019
14214
  '- **`password-editor`**, **`rich-text-editor`**, **`signature`**, **`rate-picker`**, **`color-editor`**, **`time-duration-editor`**: use when semantics match; discover **options** with GetForAI.',
@@ -14047,8 +14242,14 @@ const AI_AGENT_MOCK = [
14047
14242
  {
14048
14243
  id: AXMAiAgentWidgetChartLayoutId,
14049
14244
  name: 'widget-chart-layout',
14050
- title: M$1a('Chart Generator Agent', 'دستیار تولید نمودار'),
14051
- description: M$1a('Builds **chart visualization** widget trees (bar, line, donut, gauge, funnel, heatmap) for chat or embedded UI. Uses scoped **Widgets:GetForAI** (`agent: widget-chart-layout`) and **ListRegisteredDataSources**.', 'درخت ویجت **نمودار** (میله، خط، دونات، گیج، قیف، heatmap) برای چت؛ دستیار مستقل نمودار. از Widgets:GetForAI با scope نمودار و ListRegisteredDataSources استفاده می‌کند.'),
14245
+ title: M$1b('Chart Generator Agent', 'دستیار تولید نمودار'),
14246
+ description: M$1b('Chart visualization widgets (bar, line, donut, gauge, funnel, heatmap) from prepared data.', 'ویجت نمودار (میله، خط، دونات، ) از داده آماده.'),
14247
+ ...supervisorRouting({
14248
+ whenToUse: 'Delegate when the user wants a **chart** or visual comparison (bar, line, donut, gauge, funnel, heatmap) and you already have (or will first fetch via **platform-entity**) the underlying series/rows.',
14249
+ whenNotToUse: 'Do NOT delegate for generic forms, markdown tables, or navigation — use **widget-form-layout** or **platform-help**.',
14250
+ chainsWith: 'Chain **platform-entity** first when counts/series still need full pagination or aggregation.',
14251
+ tags: ['chart', 'visualization', 'graph'],
14252
+ }),
14052
14253
  commandIds: [
14053
14254
  aiAgentCommandBinding(axcResolveCommandRegistrySeedId(AXM_AI_REGISTRY_COMMAND_NAME.aiFormbuilderValidateLayoutJsonForAi)),
14054
14255
  ],
@@ -14080,8 +14281,13 @@ const AI_AGENT_MOCK = [
14080
14281
  {
14081
14282
  id: AXMAiAgentCommonToolsId,
14082
14283
  name: 'current-time',
14083
- title: M$1a('Current Time', 'زمان فعلی'),
14084
- description: M$1a('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.'),
14284
+ title: M$1b('Current Time', 'زمان فعلی'),
14285
+ description: M$1b('Current date/time only (common.get_current_time).', 'فقط تاریخ/زمان فعلی.'),
14286
+ ...supervisorRouting({
14287
+ whenToUse: 'Delegate only when the user explicitly needs **current date/time**, clock, timezone, or locale-specific “what time is it”.',
14288
+ whenNotToUse: 'Never for greetings, thanks, small talk, connectivity tests, or unrelated platform tasks.',
14289
+ tags: ['time', 'clock', 'timezone'],
14290
+ }),
14085
14291
  commandIds: [aiAgentCommandBinding(axcResolveCommandRegistrySeedId(AXM_AI_REGISTRY_COMMAND_NAME.commonGetCurrentTime))],
14086
14292
  queryIds: [],
14087
14293
  systemPrompt: [
@@ -14095,8 +14301,13 @@ const AI_AGENT_MOCK = [
14095
14301
  {
14096
14302
  id: AXMAiAgentImageGenerationId,
14097
14303
  name: 'image-generation',
14098
- title: M$1a('Image Generation Agent', 'دستیار تولید تصویر'),
14099
- description: M$1a('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 در کاتالوگ فرمان ثبت شده باشد. اگر ابزار تصویر موجود نیست، توضیح دهید که تولید تصویر پیکربندی نشده است.'),
14304
+ title: M$1b('Image Generation Agent', 'دستیار تولید تصویر'),
14305
+ description: M$1b('In-chat image generation (ChatGenerateImage).', 'تولید تصویر در چت.'),
14306
+ ...supervisorRouting({
14307
+ whenToUse: 'Delegate when the user asks for a **picture, illustration, diagram-as-image**, or other raster visual to generate in chat.',
14308
+ whenNotToUse: 'Not for platform navigation, entity CRUD, charts, forms, OCR of uploads, or speech — use the matching specialist.',
14309
+ tags: ['image', 'generation'],
14310
+ }),
14100
14311
  commandIds: [
14101
14312
  aiAgentCommandBinding(axcResolveCommandRegistrySeedId(AXM_AI_REGISTRY_COMMAND_NAME.imageGeneration), {
14102
14313
  model: AXMAiModelStableIds.openaiGptImage1,
@@ -14108,7 +14319,8 @@ const AI_AGENT_MOCK = [
14108
14319
  'You are the image-generation specialist for ACoreX.',
14109
14320
  'When AiManagement:ChatGenerateImage is available, call it for image requests with a detailed prompt (subject, style, composition).',
14110
14321
  'After success the platform shows the image automatically — user-visible text is **one short friendly sentence** only (e.g. “I made a cartoon version of your cat.”).',
14111
- 'Never paste tool JSON, fileId, mimeType, or storage details in text.',
14322
+ 'When the user asks to **download** the image (save/export file), include a structured file segment with `"isDownloadable": true`; otherwise the runtime attaches inline preview (default).',
14323
+ 'Never paste tool JSON, fileId, or storage details in text.',
14112
14324
  'If you have no tools, clearly state that image generation is not available in this environment.',
14113
14325
  ].join('\n'),
14114
14326
  modelEntityId: null,
@@ -14118,9 +14330,18 @@ const AI_AGENT_MOCK = [
14118
14330
  {
14119
14331
  id: AXMAiAgentSpeechToTextId,
14120
14332
  name: 'speech-to-text',
14121
- title: M$1a('Speech-to-Text Agent', 'دستیار گفتار به متن'),
14122
- description: M$1a('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) تنظیم می‌شود.'),
14123
- commandIds: [aiAgentCommandBinding(axcResolveCommandRegistrySeedId(AXM_AI_REGISTRY_COMMAND_NAME.chatTranscribeSpeech))],
14333
+ title: M$1b('Speech-to-Text Agent', 'دستیار گفتار به متن'),
14334
+ description: M$1b('Speech-to-text for attached audio (ChatTranscribeSpeech).', 'گفتار به متن برای صوت پیوست‌شده.'),
14335
+ ...supervisorRouting({
14336
+ whenToUse: 'Delegate when the user wants **transcription** of attached audio or voice notes (needs fileId in chat).',
14337
+ whenNotToUse: 'Not for text-to-speech, images, navigation, or entity data.',
14338
+ tags: ['speech', 'transcribe', 'audio'],
14339
+ }),
14340
+ commandIds: [
14341
+ aiAgentCommandBinding(axcResolveCommandRegistrySeedId(AXM_AI_REGISTRY_COMMAND_NAME.chatTranscribeSpeech), {
14342
+ model: AXMAiModelStableIds.openaiWhisper1,
14343
+ }),
14344
+ ],
14124
14345
  queryIds: [],
14125
14346
  systemPrompt: [
14126
14347
  'You are the speech-to-text specialist for ACoreX.',
@@ -14135,15 +14356,27 @@ const AI_AGENT_MOCK = [
14135
14356
  {
14136
14357
  id: AXMAiAgentTextToSpeechId,
14137
14358
  name: 'text-to-speech',
14138
- title: M$1a('Text-to-Speech Agent', 'دستیار متن به گفتار'),
14139
- description: M$1a('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) می‌آید.'),
14140
- commandIds: [aiAgentCommandBinding(axcResolveCommandRegistrySeedId(AXM_AI_REGISTRY_COMMAND_NAME.chatSynthesizeSpeech))],
14359
+ title: M$1b('Text-to-Speech Agent', 'دستیار متن به گفتار'),
14360
+ description: M$1b('Text-to-speech / read-aloud (ChatSynthesizeSpeech).', 'متن به گفتار / خواندن متن.'),
14361
+ ...supervisorRouting({
14362
+ whenToUse: 'Delegate when the user wants **spoken audio**, read-aloud, or TTS from text they provided.',
14363
+ whenNotToUse: 'Not for transcribing uploads, images, or platform data tasks.',
14364
+ tags: ['tts', 'speech', 'audio'],
14365
+ }),
14366
+ commandIds: [
14367
+ aiAgentCommandBinding(axcResolveCommandRegistrySeedId(AXM_AI_REGISTRY_COMMAND_NAME.chatSynthesizeSpeech), {
14368
+ model: AXMAiModelStableIds.openaiTts1,
14369
+ }),
14370
+ ],
14141
14371
  queryIds: [],
14372
+ outputContract: 'file',
14142
14373
  systemPrompt: [
14143
14374
  'You are the text-to-speech specialist for ACoreX.',
14144
14375
  'When the user wants text read aloud, a voice clip, or speech synthesis, call AiManagement:ChatSynthesizeSpeech with a clear text string (usually from the specialist task query).',
14145
14376
  'Omit model and voice in the tool call when defaults are set on this assist\u2019s delegated row.',
14146
- 'After success, tell the user they can play the audio from the chat tool result.',
14377
+ 'After success the platform plays the audio automatically — user-visible text is **one short friendly sentence** only (e.g. “Here is your audio clip.”).',
14378
+ 'When the user asks for a **downloadable** audio file, include a structured file segment with `"isDownloadable": true`; otherwise inline playback (default).',
14379
+ 'Never paste tool JSON, fileId, or storage details in text.',
14147
14380
  ].join('\n'),
14148
14381
  modelEntityId: null,
14149
14382
  maxSteps: 6,
@@ -14152,8 +14385,13 @@ const AI_AGENT_MOCK = [
14152
14385
  {
14153
14386
  id: AXMAiAgentDocumentOcrId,
14154
14387
  name: 'document-ocr',
14155
- title: M$1a('Document Understanding Agent', 'دستیار درک اسناد'),
14156
- description: M$1a('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 ذخیره‌شده. جایگزین تفسیر پزشکی حرفه‌ای نیست.'),
14388
+ title: M$1b('Document Understanding Agent', 'دستیار درک اسناد'),
14389
+ description: M$1b('OCR / text extraction from attached document or photo images.', 'استخراج متن از تصویر سند یا عکس پیوست‌شده.'),
14390
+ ...supervisorRouting({
14391
+ whenToUse: 'Delegate when the user attached an **image/scan** and needs **readable text** extracted (forms, handwriting, paperwork) — not for generating new images.',
14392
+ whenNotToUse: 'Not for menu help, entity lists, charts, or layout widgets.',
14393
+ tags: ['ocr', 'document', 'scan'],
14394
+ }),
14157
14395
  commandIds: [aiAgentCommandBinding(axcResolveCommandRegistrySeedId(AXM_AI_REGISTRY_COMMAND_NAME.extractDocumentText))],
14158
14396
  queryIds: [],
14159
14397
  systemPrompt: [
@@ -14171,13 +14409,13 @@ const AI_AGENT_MOCK = [
14171
14409
 
14172
14410
  //#region ---- Imports ----
14173
14411
  //#endregion
14174
- const M$19 = createMultiLanguageString;
14412
+ const M$1a = createMultiLanguageString;
14175
14413
  //#region ---- Helpers ----
14176
14414
  function aiModelRef(catalogId) {
14177
14415
  const row = AI_MODEL_MOCK.find((m) => m.id === catalogId);
14178
14416
  return {
14179
14417
  id: catalogId,
14180
- title: row?.title ?? M$19('Unknown model', 'مدل نامشخص'),
14418
+ title: row?.title ?? M$1a('Unknown model', 'مدل نامشخص'),
14181
14419
  name: row?.name ?? '',
14182
14420
  };
14183
14421
  }
@@ -14199,21 +14437,20 @@ const AI_ASSIST_MOCK = [
14199
14437
  {
14200
14438
  id: AXMAiPlatformAssistantAssistId,
14201
14439
  name: 'platform-assistant',
14202
- title: M$19('Platform Assistant', 'دستیار پلتفرم'),
14203
- description: M$19('Default platform assistant used when no specific assist is selected.', 'دستیار پیش‌فرض پلتفرم وقتی هیچ assist مشخصی انتخاب نشده باشد.'),
14204
- modelId: AXMAiModelStableIds.gpt54,
14205
- aiModel: aiModelRef(AXMAiModelStableIds.gpt54),
14440
+ title: M$1a('Platform Assistant', 'دستیار پلتفرم'),
14441
+ description: M$1a('Default platform assistant used when no specific assist is selected.', 'دستیار پیش‌فرض پلتفرم وقتی هیچ assist مشخصی انتخاب نشده باشد.'),
14442
+ modelId: AXMAiModelStableIds.openrouterQwen3Next80bA3bInstructFree,
14443
+ aiModel: aiModelRef(AXMAiModelStableIds.openrouterQwen3Next80bA3bInstructFree),
14206
14444
  tools: [],
14207
14445
  systemPrompt: 'You are a helpful assistant for the ACoreX platform. Be **brief**, accurate, and safe. Skip jargon unless the user asks for technical detail.',
14208
14446
  initialMessages: '',
14209
14447
  starterPrompts: [
14210
- { text: M$19('Where do I find a menu or feature in the platform?', 'منو یا قابلیت را در پلتفرم کجا پیدا کنم؟') },
14211
- { text: M$19('Help me list records for an entity', 'لیست رکوردهای یک موجودیت را نشان بده') },
14212
- { text: M$19('Summarize what this assist can do', 'خلاصه کن این دستیار چه کارهایی می‌تواند انجام دهد') },
14448
+ { text: M$1a('Where do I find a menu or feature in the platform?', 'منو یا قابلیت را در پلتفرم کجا پیدا کنم؟') },
14449
+ { text: M$1a('Help me list records for an entity', 'لیست رکوردهای یک موجودیت را نشان بده') },
14450
+ { text: M$1a('Summarize what this assist can do', 'خلاصه کن این دستیار چه کارهایی می‌تواند انجام دهد') },
14213
14451
  ],
14214
14452
  professionImageUrl: '',
14215
14453
  planningMode: 'once',
14216
- ...axcAiRuleRefsByIds(AXMAiRuleMarkdownId),
14217
14454
  delegatedAgents: [
14218
14455
  {
14219
14456
  agent: {
@@ -14268,17 +14505,17 @@ const AI_ASSIST_MOCK = [
14268
14505
  {
14269
14506
  id: 'b0000001-0000-4000-8000-000000000002',
14270
14507
  name: 'medical-assistant',
14271
- title: M$19('Medical Assistant', 'دستیار پزشکی'),
14272
- description: M$19('Assists with medical terminology, basic health information, and appointment-related questions.', 'کمک به اصطلاحات پزشکی، اطلاعات عمومی سلامت و پرسش‌های مرتبط با نوبت.'),
14508
+ title: M$1a('Medical Assistant', 'دستیار پزشکی'),
14509
+ description: M$1a('Assists with medical terminology, basic health information, and appointment-related questions.', 'کمک به اصطلاحات پزشکی، اطلاعات عمومی سلامت و پرسش‌های مرتبط با نوبت.'),
14273
14510
  modelId: AXMAiModelStableIds.gemini25Flash,
14274
14511
  aiModel: aiModelRef(AXMAiModelStableIds.gemini25Flash),
14275
14512
  tools: [],
14276
14513
  systemPrompt: 'You are a helpful medical assistant. You provide general health information and help users understand medical terms. You never give diagnoses; always recommend consulting a healthcare professional for medical decisions.',
14277
14514
  initialMessages: "Hello! I'm your medical assistant. I can help with general health questions and medical terminology. How can I help you today?",
14278
14515
  starterPrompts: [
14279
- { text: M$19('What does this medical term mean?', 'معنی این اصطلاح پزشکی چیست؟') },
14280
- { text: M$19('Explain common symptoms in plain language', 'علائم رایج را به زبان ساده توضیح بده') },
14281
- { text: M$19('How do I prepare for a doctor visit?', 'برای مراجعه به پزشک چه کارهایی انجام دهم؟') },
14516
+ { text: M$1a('What does this medical term mean?', 'معنی این اصطلاح پزشکی چیست؟') },
14517
+ { text: M$1a('Explain common symptoms in plain language', 'علائم رایج را به زبان ساده توضیح بده') },
14518
+ { text: M$1a('How do I prepare for a doctor visit?', 'برای مراجعه به پزشک چه کارهایی انجام دهم؟') },
14282
14519
  ],
14283
14520
  professionImageUrl: '',
14284
14521
  planningMode: 'off',
@@ -14286,16 +14523,16 @@ const AI_ASSIST_MOCK = [
14286
14523
  {
14287
14524
  id: 'b0000001-0000-4000-8000-000000000003',
14288
14525
  name: 'general-assistant',
14289
- title: M$19('General Assistant', 'دستیار عمومی'),
14290
- description: M$19('A general-purpose assistant that routes to platform help/navigation, platform entity tooling, utilities, media, image, and delegated layout specialists.', 'دستیار چندمنظوره که به دستیار راهنمای پلتفرم، موجودیت پلتفرم، ابزارها، رسانه‌ها، تصویر و چیدمان (delegated specialists) متصل می‌شود.'),
14526
+ title: M$1a('General Assistant', 'دستیار عمومی'),
14527
+ description: M$1a('A general-purpose assistant that routes to platform help/navigation, platform entity tooling, utilities, media, image, and delegated layout specialists.', 'دستیار چندمنظوره که به دستیار راهنمای پلتفرم، موجودیت پلتفرم، ابزارها، رسانه‌ها، تصویر و چیدمان (delegated specialists) متصل می‌شود.'),
14291
14528
  modelId: AXMAiModelStableIds.gemini25Flash,
14292
14529
  aiModel: aiModelRef(AXMAiModelStableIds.gemini25Flash),
14293
14530
  tools: [],
14294
14531
  systemPrompt: 'You are a helpful, friendly assistant. Be **brief**; use everyday language unless the user wants technical identifiers.',
14295
14532
  initialMessages: 'Hi! How can I help you today?',
14296
14533
  starterPrompts: [
14297
- { text: M$19('How can you help me today?', 'امروز چطور می‌توانی کمکم کنی؟') },
14298
- { text: M$19('Show me how to navigate the app', 'راهنماییم کن چطور در برنامه جابه‌جا شوم') },
14534
+ { text: M$1a('How can you help me today?', 'امروز چطور می‌توانی کمکم کنی؟') },
14535
+ { text: M$1a('Show me how to navigate the app', 'راهنماییم کن چطور در برنامه جابه‌جا شوم') },
14299
14536
  ],
14300
14537
  professionImageUrl: '',
14301
14538
  delegatedAgents: [
@@ -14342,11 +14579,11 @@ const AI_ASSIST_MOCK = [
14342
14579
  {
14343
14580
  id: AXMAiDemisAssistId,
14344
14581
  name: 'demis-payment-guide',
14345
- title: M$19('Magfa Assistant', 'دستیار هوشمند مرکز گسترش فناوری اطلاعات'),
14582
+ title: M$1a('Magfa Assistant', 'دستیار هوشمند مرکز گسترش فناوری اطلاعات'),
14346
14583
  metadata: {
14347
14584
  agent_uuid: AXMAiDemisAssistAgentUuid,
14348
14585
  },
14349
- description: M$19('Priority guide for the centralized commerce payment system. Typical questions: paying via e-wallet, withdrawing from the wallet, charging or topping up the wallet, reporting and transaction history.', 'راهنمای اولویت‌دار سامانه پرداخت متمرکز تجارت. نمونهٔ سوالات: نحوهٔ پرداخت از طریق کیف پول الکترونیک، برداشت از کیف پول، شارژ کیف پول، گزارش‌گیری و تاریخچهٔ تراکنش‌ها.'),
14586
+ description: M$1a('Priority guide for the centralized commerce payment system. Typical questions: paying via e-wallet, withdrawing from the wallet, charging or topping up the wallet, reporting and transaction history.', 'راهنمای اولویت‌دار سامانه پرداخت متمرکز تجارت. نمونهٔ سوالات: نحوهٔ پرداخت از طریق کیف پول الکترونیک، برداشت از کیف پول، شارژ کیف پول، گزارش‌گیری و تاریخچهٔ تراکنش‌ها.'),
14350
14587
  modelId: AXMAiModelStableIds.demisAi,
14351
14588
  aiModel: aiModelRef(AXMAiModelStableIds.demisAi),
14352
14589
  tools: [],
@@ -14359,34 +14596,46 @@ const AI_ASSIST_MOCK = [
14359
14596
  ].join('\n'),
14360
14597
  initialMessages: '',
14361
14598
  starterPrompts: [
14362
- { text: M$19('How do I pay using the e-wallet?', 'چگونه با کیف پول الکترونیک پرداخت کنم؟') },
14363
- { text: M$19('How can I withdraw from my wallet?', 'چگونه از کیف پول برداشت کنم؟') },
14364
- { text: M$19('How do I top up or charge my wallet?', 'چگونه کیف پول را شارژ کنم؟') },
14365
- { text: M$19('How do I view transaction history and reports?', 'چگونه تاریخچه تراکنش‌ها و گزارش‌ها را ببینم؟') },
14599
+ { text: M$1a('How do I pay using the e-wallet?', 'چگونه با کیف پول الکترونیک پرداخت کنم؟') },
14600
+ { text: M$1a('How can I withdraw from my wallet?', 'چگونه از کیف پول برداشت کنم؟') },
14601
+ { text: M$1a('How do I top up or charge my wallet?', 'چگونه کیف پول را شارژ کنم؟') },
14602
+ { text: M$1a('How do I view transaction history and reports?', 'چگونه تاریخچه تراکنش‌ها و گزارش‌ها را ببینم؟') },
14366
14603
  ],
14367
14604
  professionImageUrl: '',
14368
- speechModelId: AXMAiModelStableIds.demisAi,
14369
14605
  planningMode: 'off',
14370
- delegatedAgents: [],
14606
+ delegatedAgents: [
14607
+ {
14608
+ agent: {
14609
+ type: AXMAiAgentSpeechToTextId,
14610
+ options: { model: AXMAiModelStableIds.demisAi },
14611
+ },
14612
+ },
14613
+ ],
14371
14614
  },
14372
14615
  {
14373
14616
  id: AXMAiDemisGeneralAssistId,
14374
14617
  name: 'demis-general',
14375
- title: M$19('Demis General', 'دیمیس عمومی'),
14376
- description: M$19('General-purpose Demisco chat using the Demis AI model without a configured agent.', 'چت عمومی Demisco با مدل Demis AI بدون agent پیکربندی‌شده.'),
14618
+ title: M$1a('Demis General', 'دیمیس عمومی'),
14619
+ description: M$1a('General-purpose Demisco chat using the Demis AI model without a configured agent.', 'چت عمومی Demisco با مدل Demis AI بدون agent پیکربندی‌شده.'),
14377
14620
  modelId: AXMAiModelStableIds.demisAi,
14378
14621
  aiModel: aiModelRef(AXMAiModelStableIds.demisAi),
14379
14622
  tools: [],
14380
14623
  systemPrompt: 'You are a helpful, friendly assistant powered by Demisco Demis AI. Be brief and accurate unless the user asks for detail.',
14381
14624
  initialMessages: '',
14382
14625
  starterPrompts: [
14383
- { text: M$19('How can you help me today?', 'امروز چطور می‌توانی کمکم کنی؟') },
14384
- { text: M$19('Summarize what you can do', 'خلاصه کن چه کارهایی می‌توانی انجام دهی') },
14626
+ { text: M$1a('How can you help me today?', 'امروز چطور می‌توانی کمکم کنی؟') },
14627
+ { text: M$1a('Summarize what you can do', 'خلاصه کن چه کارهایی می‌توانی انجام دهی') },
14385
14628
  ],
14386
14629
  professionImageUrl: '',
14387
- speechModelId: AXMAiModelStableIds.demisAi,
14388
14630
  planningMode: 'off',
14389
- delegatedAgents: [],
14631
+ delegatedAgents: [
14632
+ {
14633
+ agent: {
14634
+ type: AXMAiAgentSpeechToTextId,
14635
+ options: { model: AXMAiModelStableIds.demisAi },
14636
+ },
14637
+ },
14638
+ ],
14390
14639
  },
14391
14640
  ];
14392
14641
  //#endregion
@@ -14399,10 +14648,7 @@ class AXCAiAssistSeeder {
14399
14648
  this.storageService = inject(AXPEntityStorageService);
14400
14649
  }
14401
14650
  async seed() {
14402
- const entityName = `${RootConfig.module.name}.${RootConfig.entities.assist.name}`;
14403
- for (const assist of AI_ASSIST_MOCK) {
14404
- await this.storageService.upsertOne(entityName, assist, { merge: true });
14405
- }
14651
+ await this.storageService.initial(`${RootConfig.module.name}.${RootConfig.entities.assist.name}`, AI_ASSIST_MOCK);
14406
14652
  }
14407
14653
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXCAiAssistSeeder, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
14408
14654
  static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXCAiAssistSeeder }); }
@@ -14513,13 +14759,11 @@ function axpAiExtractStoredFileArtifactFromUnknown(content) {
14513
14759
  }
14514
14760
  function axpAiExtractStoredFileArtifactFromDataRecord(d) {
14515
14761
  const fileId = typeof d['fileId'] === 'string' ? d['fileId'].trim() : '';
14516
- const mimeType = typeof d['mimeType'] === 'string' ? d['mimeType'].trim() : '';
14517
- if (!fileId || !mimeType) {
14762
+ if (!fileId) {
14518
14763
  return null;
14519
14764
  }
14520
- const nameRaw = d['name'];
14521
- const name = typeof nameRaw === 'string' && nameRaw.trim() ? nameRaw.trim() : undefined;
14522
- return { fileId, mimeType, ...(name ? { name } : {}) };
14765
+ const isDownloadable = d['isDownloadable'] === true;
14766
+ return isDownloadable ? { fileId, isDownloadable: true } : { fileId };
14523
14767
  }
14524
14768
  function axpAiExtractLastStoredFileArtifactFromChatMessages(messages) {
14525
14769
  let last = null;
@@ -14564,7 +14808,7 @@ function axpAiDelegatedSubTranscriptAppendFileArtifactFromToolResults(messages)
14564
14808
  return out;
14565
14809
  }
14566
14810
  const msg = out[lastAssistant];
14567
- const duplicate = msg.responses.some((r) => r.type === 'file' && r.content.fileId === artifact.fileId && r.content.mimeType === artifact.mimeType);
14811
+ const duplicate = msg.responses.some((r) => r.type === 'file' && r.content.fileId === artifact.fileId);
14568
14812
  if (duplicate) {
14569
14813
  return out;
14570
14814
  }
@@ -14591,7 +14835,11 @@ function axpAiIsDelegatedAgentResultSegment(value) {
14591
14835
  }
14592
14836
  if (t === 'file' && o['content'] != null && typeof o['content'] === 'object' && !Array.isArray(o['content'])) {
14593
14837
  const c = o['content'];
14594
- return typeof c['fileId'] === 'string' && typeof c['mimeType'] === 'string';
14838
+ if (typeof c['fileId'] !== 'string') {
14839
+ return false;
14840
+ }
14841
+ const dl = c['isDownloadable'];
14842
+ return dl === undefined || dl === false || dl === true;
14595
14843
  }
14596
14844
  if (t === 'followUp' && Array.isArray(o['content'])) {
14597
14845
  return axpAiNormalizeFollowUpContent(o['content']).length > 0;
@@ -14813,6 +15061,7 @@ function axpAiChatMessagesFromProviderAssistant(text, toolCalls) {
14813
15061
  arguments: tc.arguments,
14814
15062
  },
14815
15063
  callId: tc.id,
15064
+ ...(tc.metadata ? { metadata: { ...tc.metadata } } : {}),
14816
15065
  }
14817
15066
  : {
14818
15067
  type: 'tool',
@@ -14821,6 +15070,7 @@ function axpAiChatMessagesFromProviderAssistant(text, toolCalls) {
14821
15070
  arguments: tc.arguments,
14822
15071
  },
14823
15072
  callId: tc.id,
15073
+ ...(tc.metadata ? { metadata: { ...tc.metadata } } : {}),
14824
15074
  },
14825
15075
  ],
14826
15076
  });
@@ -14845,6 +15095,7 @@ function axpAiToolCallFromAssistantToolMessage(message) {
14845
15095
  id: callId || `call_${command}`,
14846
15096
  name: command,
14847
15097
  arguments: r.content.arguments,
15098
+ ...(r.metadata ? { metadata: { ...r.metadata } } : {}),
14848
15099
  };
14849
15100
  }
14850
15101
  }
@@ -15187,6 +15438,36 @@ function axpAiChatDelegatedReflectionAssistantMessage(reflectionText) {
15187
15438
 
15188
15439
  //#region ---- Imports ----
15189
15440
  //#endregion
15441
+ //#region ---- Delegated invocation rule overrides ----
15442
+ /** Supervisor tool arg: optional {@link AiRule} names for this specialist sub-run only (not assist run rules). */
15443
+ const AXPAI_DELEGATED_INVOCATION_INCLUDE_RULES_KEY = 'includeRules';
15444
+ /** Supervisor tool arg: optional rule names to omit on this specialist sub-run. */
15445
+ const AXPAI_DELEGATED_INVOCATION_EXCLUDE_RULES_KEY = 'excludeRules';
15446
+ function normalizeDelegatedRuleNameList(raw) {
15447
+ if (raw == null) {
15448
+ return [];
15449
+ }
15450
+ return castArray(raw)
15451
+ .map((entry) => (isString(entry) ? entry.trim() : ''))
15452
+ .filter((name) => name.length > 0);
15453
+ }
15454
+ /**
15455
+ * Strips per-invocation rule overrides from merged specialist args before building the sub-run user message.
15456
+ * Assist-level and parent-run `includeRules` must not flow into delegated agents unless passed here.
15457
+ */
15458
+ function extractDelegatedInvocationRuleOverrides(args) {
15459
+ const includeRules = normalizeDelegatedRuleNameList(args[AXPAI_DELEGATED_INVOCATION_INCLUDE_RULES_KEY]);
15460
+ const excludeRules = normalizeDelegatedRuleNameList(args[AXPAI_DELEGATED_INVOCATION_EXCLUDE_RULES_KEY]);
15461
+ const argsWithoutRuleKeys = { ...args };
15462
+ delete argsWithoutRuleKeys[AXPAI_DELEGATED_INVOCATION_INCLUDE_RULES_KEY];
15463
+ delete argsWithoutRuleKeys[AXPAI_DELEGATED_INVOCATION_EXCLUDE_RULES_KEY];
15464
+ return {
15465
+ args: argsWithoutRuleKeys,
15466
+ ...(includeRules.length > 0 ? { includeRules } : {}),
15467
+ ...(excludeRules.length > 0 ? { excludeRules } : {}),
15468
+ };
15469
+ }
15470
+ //#endregion
15190
15471
  //#region ---- Default supervisor tool schema (delegated agent) ----
15191
15472
  /** Default JSON Schema for supervisor → specialist when {@link AXMAiAgentRow.parameterDefinitions} is empty. */
15192
15473
  const AXPAI_DEFAULT_DELEGATED_AGENT_PARAMETERS_SCHEMA = {
@@ -15196,6 +15477,16 @@ const AXPAI_DEFAULT_DELEGATED_AGENT_PARAMETERS_SCHEMA = {
15196
15477
  type: 'string',
15197
15478
  description: 'Clear instruction or question for the specialist agent.',
15198
15479
  },
15480
+ [AXPAI_DELEGATED_INVOCATION_INCLUDE_RULES_KEY]: {
15481
+ type: 'array',
15482
+ items: { type: 'string' },
15483
+ description: 'Optional AiRule programmatic names (e.g. markdown, end-user-language) for this specialist call only. Omit unless the sub-task needs them.',
15484
+ },
15485
+ [AXPAI_DELEGATED_INVOCATION_EXCLUDE_RULES_KEY]: {
15486
+ type: 'array',
15487
+ items: { type: 'string' },
15488
+ description: 'Optional AiRule names to suppress on this specialist call (including rules on the AiAgent catalog row).',
15489
+ },
15199
15490
  },
15200
15491
  required: ['query'],
15201
15492
  additionalProperties: false,
@@ -15528,13 +15819,119 @@ function resolveDelegatedAssistOptionString(assist, agentId, key) {
15528
15819
  function resolveDelegatedAssistOptionModel(assist, agentId) {
15529
15820
  return resolveDelegatedAssistOptionString(assist, agentId, 'model');
15530
15821
  }
15531
- /** Optional assist-level speech catalog id (mock seed / custom rows). */
15822
+ /** Speech catalog id from the speech-to-text delegated specialist row (`delegatedAgents[].agent.options.model`). */
15532
15823
  function resolveAssistSpeechModelId(assist) {
15533
- if (assist == null || typeof assist !== 'object') {
15534
- return undefined;
15824
+ return resolveDelegatedAssistOptionModel(assist, AXMAiAgentSpeechToTextId);
15825
+ }
15826
+ //#endregion
15827
+
15828
+ //#region ---- Imports ----
15829
+ //#endregion
15830
+ //#region ---- Resolvers ----
15831
+ function resolveMlOrPlain(value, locale = 'en-US') {
15832
+ if (value == null) {
15833
+ return '';
15535
15834
  }
15536
- const v = assist['speechModelId'];
15537
- return typeof v === 'string' && v.trim() ? v.trim() : undefined;
15835
+ if (typeof value === 'string') {
15836
+ return value.trim();
15837
+ }
15838
+ return resolveMultiLanguageString(value, locale).trim();
15839
+ }
15840
+ function trimPlainString(value) {
15841
+ return typeof value === 'string' ? value.trim() : '';
15842
+ }
15843
+ function normalizeIntentTags(tags) {
15844
+ if (!Array.isArray(tags)) {
15845
+ return [];
15846
+ }
15847
+ return tags
15848
+ .filter((t) => typeof t === 'string' && t.trim().length > 0)
15849
+ .map((t) => t.trim());
15850
+ }
15851
+ //#endregion
15852
+ //#region ---- Per-agent routing blocks ----
15853
+ /**
15854
+ * Standard routing body for one specialist (shared by tool `description` and system catalog).
15855
+ */
15856
+ function axcFormatSupervisorAgentRoutingBody(agent, locale = 'en-US') {
15857
+ const sections = [];
15858
+ const whenTo = trimPlainString(agent.supervisorWhenToUse);
15859
+ if (whenTo.length > 0) {
15860
+ sections.push(`When to delegate:\n${whenTo}`);
15861
+ }
15862
+ const whenNot = trimPlainString(agent.supervisorWhenNotToUse);
15863
+ if (whenNot.length > 0) {
15864
+ sections.push(`When NOT to delegate:\n${whenNot}`);
15865
+ }
15866
+ const chains = trimPlainString(agent.supervisorChainsWith);
15867
+ if (chains.length > 0) {
15868
+ sections.push(`Chaining:\n${chains}`);
15869
+ }
15870
+ const tags = normalizeIntentTags(agent.supervisorIntentTags);
15871
+ if (tags.length > 0) {
15872
+ sections.push(`Intent tags: ${tags.join(', ')}`);
15873
+ }
15874
+ return sections.join('\n\n').trim();
15875
+ }
15876
+ /**
15877
+ * Builds the LLM tool `description` for a delegated `agent:<id>` tool from catalog routing fields.
15878
+ */
15879
+ function axcFormatSupervisorAgentToolDescription(agent, locale = 'en-US') {
15880
+ const summary = resolveMlOrPlain(agent.description, locale) ||
15881
+ resolveMlOrPlain(agent.title, locale) ||
15882
+ agent.name?.trim() ||
15883
+ '';
15884
+ const parts = [];
15885
+ if (summary.length > 0) {
15886
+ parts.push(summary);
15887
+ }
15888
+ const routing = axcFormatSupervisorAgentRoutingBody(agent, locale);
15889
+ if (routing.length > 0) {
15890
+ parts.push(routing);
15891
+ }
15892
+ return parts.join('\n\n').trim();
15893
+ }
15894
+ //#endregion
15895
+ //#region ---- System prompt catalog (resolved assist roster) ----
15896
+ /**
15897
+ * After {@link resolveAgentsForAssist} (assist `delegatedAgents` + run include/exclude), builds a
15898
+ * supervisor system addendum listing only specialists available on this run.
15899
+ */
15900
+ function axcBuildSupervisorDelegationSystemAddendum(agents) {
15901
+ if (agents.length === 0) {
15902
+ return '';
15903
+ }
15904
+ const header = [
15905
+ '## Specialists for this assist (resolved roster)',
15906
+ 'Only the delegated `agent:<catalog-id>` tools below are available on this run (assist configuration plus any include/exclude filters).',
15907
+ 'Pick tools using each tool’s description in the function list; this section is the same routing in catalog order.',
15908
+ '',
15909
+ ].join('\n');
15910
+ const blocks = [];
15911
+ for (const agent of agents) {
15912
+ const id = agent.id?.trim() ?? '';
15913
+ if (!id) {
15914
+ continue;
15915
+ }
15916
+ const toolName = axpAiSupervisorAgentToolName(id);
15917
+ const catalogName = agent.name?.trim() ?? '';
15918
+ const displayTitle = resolveMlOrPlain(agent.title) || catalogName || id;
15919
+ const headingLabel = catalogName ? `${displayTitle} (\`${catalogName}\`)` : displayTitle;
15920
+ const lines = [`### ${headingLabel}`, `- Tool name: \`${toolName}\``];
15921
+ const summary = resolveMlOrPlain(agent.description) || resolveMlOrPlain(agent.title);
15922
+ if (summary.length > 0) {
15923
+ lines.push(`- Summary: ${summary}`);
15924
+ }
15925
+ const routing = axcFormatSupervisorAgentRoutingBody(agent);
15926
+ if (routing.length > 0) {
15927
+ lines.push('', routing);
15928
+ }
15929
+ blocks.push(lines.join('\n'));
15930
+ }
15931
+ if (blocks.length === 0) {
15932
+ return '';
15933
+ }
15934
+ return `${header}${blocks.join('\n\n')}`;
15538
15935
  }
15539
15936
  //#endregion
15540
15937
 
@@ -16095,19 +16492,20 @@ const AXC_AI_AGENT_SYSTEM_PROMPT = '';
16095
16492
  /**
16096
16493
  * Supervisor-only orchestration (delegated `agent:` tools). Appended only on the **main assist** run when
16097
16494
  * {@link appendSupervisorAgentDelegationHint} runs — never on specialist sub-runs.
16098
- * Specialist *how-to* lives in each AiAgent `systemPrompt`; *when to call whom* lives in tool `description`
16099
- * (from catalog `title` / `description` via {@link buildAgentToolSchemas}).
16495
+ * Specialist *how-to* lives in each AiAgent `systemPrompt`; *when to call whom* lives in the delegated tool
16496
+ * `description` (from {@link axcFormatSupervisorAgentToolDescription}: summary, supervisorWhenToUse, whenNot, chains, tags).
16100
16497
  */
16101
16498
  const AXC_AI_SUPERVISOR_ORCHESTRATION_PROMPT = [
16102
16499
  '## Supervisor (delegated specialists)',
16103
16500
  '- Your tools are specialists (`agent:<AiAgent catalog id>`). Pick from the tool list using each tool’s description — do not answer platform facts from memory.',
16104
16501
  '- Pass a clear `query` or structured args. You may call more than one specialist in one turn.',
16502
+ '- **AiRule scope:** assist/conversation rules apply only to **your** supervisor turn. Specialists do **not** inherit them. Pass optional `includeRules` / `excludeRules` (string arrays of rule programmatic names) on a delegated tool call **only** when that specialist sub-task needs formatting or tone rules beyond its own catalog `rules`.',
16105
16503
  '- Read `agent_result` payloads: `success`, optional `error`, and `data.responses` (text, file, node, followUp segments).',
16106
16504
  '- **Short, direct** user replies. Synthesize specialist `text` unless the user needs verbatim navigation/catalog wording.',
16107
16505
  '',
16108
16506
  '## Relay structured UI segments',
16109
16507
  '- The runtime attaches `file`, `node`, and `followUp` segments from specialist `data.responses` to your final message — **do not** paste them as JSON in user-visible text.',
16110
- '- **Images / files**: never include `{"type":"file",...}`, `fileId`, mimeType, or storage payloads in text. The UI renders the asset from the structured segment. Add at most **one** friendly sentence (e.g. “Your cartoon version is ready.”).',
16508
+ '- **Images / files**: never include `{"type":"file",...}`, `fileId`, or storage payloads in user-visible text. The runtime attaches file segments from tool results (`content.fileId` only; optional `isDownloadable: true` when the user asked for a **downloadable** file — default false for inline preview/playback). Add at most **one** friendly sentence (e.g. “Your cartoon version is ready.”).',
16111
16509
  '- **`node` / `followUp` only** — when the runtime did not already attach them, include the JSON envelope in your final message (no markdown fences):',
16112
16510
  ' - `{"type":"node","content": <AXPWidgetNode>}` — wrap inner layout trees; never paste bare inner widget JSON.',
16113
16511
  ' - `{"type":"followUp","content":[{"text":"...","command":{"name":"...","options":{}}}, ...]}` — next-step chips.',
@@ -16199,7 +16597,7 @@ function buildAgentToolSchemas(agents) {
16199
16597
  continue;
16200
16598
  }
16201
16599
  const params = resolveDelegatedAgentFullParametersSchema(a);
16202
- const descCore = axcResolveAiMlOrPlainString(a.description) || axcResolveAiMlOrPlainString(a.title) || a.name?.trim() || id;
16600
+ const descCore = axcFormatSupervisorAgentToolDescription(a) || id;
16203
16601
  const labelParts = [];
16204
16602
  const resolvedTitle = axcResolveAiMlOrPlainString(a.title);
16205
16603
  if (resolvedTitle.length > 0) {
@@ -16225,6 +16623,16 @@ function appendSupervisorAgentDelegationHint(base) {
16225
16623
  const block = AXC_AI_SUPERVISOR_ORCHESTRATION_PROMPT;
16226
16624
  return base.trim() ? `${base.trim()}\n\n${block}` : block;
16227
16625
  }
16626
+ /**
16627
+ * Appends per-assist specialist routing catalog (resolved agents after include/exclude) to the supervisor system prompt.
16628
+ */
16629
+ function appendSupervisorDelegationCatalogHint(base, agents) {
16630
+ const catalog = axcBuildSupervisorDelegationSystemAddendum(agents);
16631
+ if (!catalog.trim()) {
16632
+ return base.trim();
16633
+ }
16634
+ return base.trim() ? `${base.trim()}\n\n${catalog}` : catalog;
16635
+ }
16228
16636
  const AGENT_SUB_RUN_CONTEXT_MAX_CHARS = 8_000;
16229
16637
  /**
16230
16638
  * User message for a delegated agent sub-run: structured args plus a trimmed transcript tail.
@@ -16246,8 +16654,6 @@ function formatTranscriptTailLineForMessage(m) {
16246
16654
  }
16247
16655
  let text = axpAiChatMessageGetText(m);
16248
16656
  if (role === 'user') {
16249
- const imageHints = [];
16250
- const audioHints = [];
16251
16657
  const fileHints = [];
16252
16658
  for (const r of m.responses) {
16253
16659
  if (r.type !== 'file') {
@@ -16257,31 +16663,10 @@ function formatTranscriptTailLineForMessage(m) {
16257
16663
  if (!id) {
16258
16664
  continue;
16259
16665
  }
16260
- const name = r.content.name?.trim();
16261
- const hint = name ? `fileId=${id} name=${name}` : `fileId=${id}`;
16262
- const mime = r.content.mimeType?.trim().toLowerCase() ?? '';
16263
- if (mime.startsWith('image/')) {
16264
- imageHints.push(hint);
16265
- }
16266
- else if (mime.startsWith('audio/')) {
16267
- audioHints.push(hint);
16268
- }
16269
- else {
16270
- fileHints.push(hint);
16271
- }
16272
- }
16273
- const extras = [];
16274
- if (imageHints.length > 0) {
16275
- extras.push(`[image attachments: ${imageHints.join('; ')}]`);
16276
- }
16277
- if (audioHints.length > 0) {
16278
- extras.push(`[audio attachments: ${audioHints.join('; ')}]`);
16666
+ fileHints.push(`fileId=${id}`);
16279
16667
  }
16280
16668
  if (fileHints.length > 0) {
16281
- extras.push(`[file attachments: ${fileHints.join('; ')}]`);
16282
- }
16283
- if (extras.length > 0) {
16284
- const block = extras.join('\n');
16669
+ const block = `[attachments: ${fileHints.join('; ')}]`;
16285
16670
  text = text.trim() ? `${text.trim()}\n${block}` : block;
16286
16671
  }
16287
16672
  }
@@ -16318,6 +16703,27 @@ function axcDemisAgentUuidFromAssistMetadata(assist) {
16318
16703
  const agentUuid = metadata['agent_uuid'];
16319
16704
  return typeof agentUuid === 'string' ? agentUuid.trim() : '';
16320
16705
  }
16706
+ /**
16707
+ * Speech catalog id for Demis inline audio transcription.
16708
+ * Demis chat does not use delegated specialist runs; resolution order:
16709
+ * 1. `delegatedAgents` row for {@link AXMAiAgentSpeechToTextId} → `options.model` (when configured)
16710
+ * 2. assist `modelId` (Demis assists use the Demis catalog row)
16711
+ * 3. mock default Demis model
16712
+ */
16713
+ function axcDemisSpeechModelEntityIdFromAssist(assist) {
16714
+ if (assist != null && typeof assist === 'object') {
16715
+ const row = assist;
16716
+ const fromSttAgent = resolveDelegatedAssistOptionModel(row, AXMAiAgentSpeechToTextId)?.trim();
16717
+ if (fromSttAgent) {
16718
+ return fromSttAgent;
16719
+ }
16720
+ const modelId = typeof row.modelId === 'string' ? row.modelId.trim() : '';
16721
+ if (modelId) {
16722
+ return modelId;
16723
+ }
16724
+ }
16725
+ return AXMAiModelStableIds.demisAi;
16726
+ }
16321
16727
  /** Reads `demisSessionUuid` from a Demis provider `rawResponse`. */
16322
16728
  function axcDemisSessionUuidFromProviderRaw(raw) {
16323
16729
  if (raw == null || typeof raw !== 'object' || Array.isArray(raw)) {
@@ -16348,10 +16754,10 @@ function axcDemisSessionUuidFromSseChunk(obj) {
16348
16754
  const v = o['session_uuid'] ?? o['sessionUuid'];
16349
16755
  return typeof v === 'string' ? v.trim() : '';
16350
16756
  }
16351
- /** Builds `AXPAiChatOptions.demis` from assist mock fields (`metadata.agent_uuid`, `speechModelId`). */
16757
+ /** Builds `AXPAiChatOptions.demis` from assist mock fields (`metadata.agent_uuid`, speech catalog model). */
16352
16758
  function axcDemisChatOptionsFromAssist(assist, sessionUuid) {
16353
16759
  const agentUuid = axcDemisAgentUuidFromAssistMetadata(assist);
16354
- const speechModelEntityId = resolveAssistSpeechModelId(assist)?.trim() ?? '';
16760
+ const speechModelEntityId = axcDemisSpeechModelEntityIdFromAssist(assist);
16355
16761
  const session = sessionUuid?.trim() ?? '';
16356
16762
  if (!agentUuid && !speechModelEntityId && !session) {
16357
16763
  return undefined;
@@ -16593,10 +16999,7 @@ async function buildAiChatImageBase64Cache(fileStorage, messages) {
16593
16999
  const id = r.content.fileId.trim();
16594
17000
  if (id) {
16595
17001
  ids.add(id);
16596
- const mt = r.content.mimeType?.trim();
16597
- if (mt && !mimeById.has(id)) {
16598
- mimeById.set(id, mt);
16599
- }
17002
+ // MIME type is resolved from file storage via fileId (not on the chat file segment).
16600
17003
  }
16601
17004
  }
16602
17005
  }
@@ -16882,7 +17285,6 @@ async function parseChatCompletionSseStream(response, fromOpenAiToolName, onStre
16882
17285
  let accumulatedContent = '';
16883
17286
  const streamingToolCalls = new Map();
16884
17287
  const streamState = { inThinking: false, pending: '' };
16885
- let rawChunks = [];
16886
17288
  let lastUsageChunk = null;
16887
17289
  while (true) {
16888
17290
  const { done, value } = await reader.read();
@@ -16909,7 +17311,6 @@ async function parseChatCompletionSseStream(response, fromOpenAiToolName, onStre
16909
17311
  catch {
16910
17312
  continue;
16911
17313
  }
16912
- rawChunks.push(data);
16913
17314
  processStreamChunk(data, onStreamDelta, streamState, streamingToolCalls, (content) => {
16914
17315
  accumulatedContent += content;
16915
17316
  }, (usage) => {
@@ -16935,7 +17336,6 @@ async function parseChatCompletionSseStream(response, fromOpenAiToolName, onStre
16935
17336
  catch {
16936
17337
  continue;
16937
17338
  }
16938
- rawChunks.push(data);
16939
17339
  processStreamChunk(data, onStreamDelta, streamState, streamingToolCalls, (content) => {
16940
17340
  accumulatedContent += content;
16941
17341
  }, (usage) => {
@@ -16974,11 +17374,7 @@ async function parseChatCompletionSseStream(response, fromOpenAiToolName, onStre
16974
17374
  return {
16975
17375
  messages,
16976
17376
  toolCalls: toolCalls.length > 0 ? toolCalls : undefined,
16977
- rawResponse: {
16978
- stream: true,
16979
- chunks: rawChunks,
16980
- ...(lastUsageChunk ? { usage: lastUsageChunk } : {}),
16981
- },
17377
+ ...(lastUsageChunk ? { rawResponse: { usage: lastUsageChunk } } : {}),
16982
17378
  };
16983
17379
  }
16984
17380
  //#endregion
@@ -17326,8 +17722,6 @@ function appendOpenAiUserResponsePart(r, parts, imageCache) {
17326
17722
  throw new Error(`Could not resolve chat file for OpenAI request (fileId: ${id}).`);
17327
17723
  }
17328
17724
  const mime = resolved.mimeType.trim().toLowerCase();
17329
- const rawName = r.content.name?.trim();
17330
- const displayName = rawName && rawName.length > 0 ? rawName : undefined;
17331
17725
  if (mime.startsWith('image/')) {
17332
17726
  parts.push({
17333
17727
  type: 'image_url',
@@ -17340,13 +17734,11 @@ function appendOpenAiUserResponsePart(r, parts, imageCache) {
17340
17734
  if (mime.startsWith('audio/')) {
17341
17735
  parts.push({
17342
17736
  type: 'text',
17343
- text: displayName
17344
- ? `[Audio attachment: fileId=${id} name=${displayName}]`
17345
- : `[Audio attachment: fileId=${id}]`,
17737
+ text: `[Audio attachment: fileId=${id}]`,
17346
17738
  });
17347
17739
  return;
17348
17740
  }
17349
- const filename = rawName && rawName.length > 0 ? rawName : 'attachment';
17741
+ const filename = 'attachment';
17350
17742
  if (openAiUserFileShouldInlineAsText(mime)) {
17351
17743
  const decoded = decodeUtf8FromBase64(resolved.base64);
17352
17744
  const max = 400_000;
@@ -17496,16 +17888,7 @@ function toOpenAiChatCompletionMessage(m, toOpenAiToolName, imageCache) {
17496
17888
  : r0?.type === 'file'
17497
17889
  ? (() => {
17498
17890
  const id = r0.content.fileId.trim();
17499
- const name = r0.content.name?.trim();
17500
- const mime = r0.content.mimeType?.trim().toLowerCase() ?? '';
17501
- if (mime.startsWith('audio/')) {
17502
- return name
17503
- ? `[Audio attachment: fileId=${id} name=${name}]`
17504
- : `[Audio attachment: fileId=${id}]`;
17505
- }
17506
- return name
17507
- ? `[File attachment: fileId=${id} name=${name}]`
17508
- : `[File attachment: fileId=${id}]`;
17891
+ return `[File attachment: fileId=${id}]`;
17509
17892
  })()
17510
17893
  : '';
17511
17894
  return {
@@ -17518,6 +17901,8 @@ function toOpenAiChatCompletionMessage(m, toOpenAiToolName, imageCache) {
17518
17901
  //#region ---- Imports ----
17519
17902
  /** Gemini API cap on function declarations per request. */
17520
17903
  const GEMINI_FUNCTION_DECLARATIONS_MAX = 512;
17904
+ /** {@link AXPMetaData} key on tool/agent responses and {@link AXPAiToolCall} for Gemini `thought_signature` replay. */
17905
+ const GEMINI_METADATA_THOUGHT_SIGNATURE = 'geminiThoughtSignature';
17521
17906
  //#endregion
17522
17907
  //#region ---- Mock fallback (for local testing when setting is empty) ----
17523
17908
  /** Fill with your Gemini API key for local testing when the setting is not set. */
@@ -17613,7 +17998,7 @@ class AXCAiChatGeminiProvider {
17613
17998
  });
17614
17999
  const imageCache = await buildAiChatImageBase64Cache(this.fileStorage, dialogueMessages);
17615
18000
  // Map platform-agnostic chat messages to Gemini contents (incl. functionCall / functionResponse replay).
17616
- const contents = dialogueMessagesToGeminiContents(dialogueMessages, imageCache);
18001
+ const contents = platformTranscriptToGeminiContents(dialogueMessages, imageCache);
17617
18002
  // Optional tool declarations (Gemini function calling)
17618
18003
  const tools = options.tools && options.tools.length > 0
17619
18004
  ? [
@@ -17711,10 +18096,14 @@ class AXCAiChatGeminiProvider {
17711
18096
  }
17712
18097
  }
17713
18098
  const id = `tool-${assistantCalls.length + 1}`;
18099
+ const thoughtSignature = readGeminiThoughtSignatureFromPart(part);
17714
18100
  const tc = {
17715
18101
  id,
17716
18102
  name: fromGeminiFunctionDeclarationName(part.functionCall.name),
17717
18103
  arguments: args,
18104
+ ...(thoughtSignature
18105
+ ? { metadata: { [GEMINI_METADATA_THOUGHT_SIGNATURE]: thoughtSignature } }
18106
+ : {}),
17718
18107
  };
17719
18108
  assistantCalls.push(tc);
17720
18109
  toolCalls.push(tc);
@@ -17890,8 +18279,102 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
17890
18279
  type: Injectable
17891
18280
  }] });
17892
18281
  //#region ---- Utility Methods ----
17893
- function dialogueMessagesToGeminiContents(messages, imageCache) {
17894
- return messages.map((m) => mapPlatformMessageToGeminiContent(m, imageCache));
18282
+ /**
18283
+ * Index of the latest user line with real content (text/file/node). Per Gemini docs this starts the
18284
+ * "current turn"; only function calls at or after this index require `thought_signature` on replay.
18285
+ */
18286
+ function findGeminiCurrentTurnStartIndex(messages) {
18287
+ for (let i = messages.length - 1; i >= 0; i--) {
18288
+ const m = messages[i];
18289
+ if (m.role !== 'user') {
18290
+ continue;
18291
+ }
18292
+ for (const r of m.responses) {
18293
+ if (r.type === 'text' && r.content.trim().length > 0) {
18294
+ return i;
18295
+ }
18296
+ if (r.type === 'file' || r.type === 'node') {
18297
+ return i;
18298
+ }
18299
+ }
18300
+ }
18301
+ return 0;
18302
+ }
18303
+ function readGeminiThoughtSignatureFromPart(part) {
18304
+ const raw = part.thought_signature ?? part.thoughtSignature;
18305
+ if (typeof raw === 'string' && raw.trim().length > 0) {
18306
+ return raw.trim();
18307
+ }
18308
+ return undefined;
18309
+ }
18310
+ function geminiThoughtSignatureFromMetadata(metadata) {
18311
+ if (!metadata) {
18312
+ return undefined;
18313
+ }
18314
+ const raw = metadata[GEMINI_METADATA_THOUGHT_SIGNATURE];
18315
+ return typeof raw === 'string' && raw.trim().length > 0 ? raw.trim() : undefined;
18316
+ }
18317
+ function geminiFunctionCallPartFromAssistantResponse(r, replayThoughtSignature) {
18318
+ const tc = r.content;
18319
+ const part = {
18320
+ functionCall: {
18321
+ name: toGeminiFunctionDeclarationName(tc.command),
18322
+ args: geminiStructuredArgsFromToolArguments(tc.arguments),
18323
+ },
18324
+ };
18325
+ if (replayThoughtSignature) {
18326
+ const thoughtSignature = geminiThoughtSignatureFromMetadata(r.metadata);
18327
+ if (thoughtSignature) {
18328
+ part['thought_signature'] = thoughtSignature;
18329
+ }
18330
+ }
18331
+ return part;
18332
+ }
18333
+ function assistantGroupToGeminiContent(group, replayThoughtSignature) {
18334
+ const parts = [];
18335
+ for (const msg of group) {
18336
+ for (const r of msg.responses) {
18337
+ if (r.type === 'text' && r.content.trim()) {
18338
+ parts.push({ text: r.content });
18339
+ }
18340
+ if (r.type === 'think' && r.content.trim()) {
18341
+ parts.push({ text: `<think>${r.content}</think>` });
18342
+ }
18343
+ if (r.type === 'tool' || r.type === 'agent') {
18344
+ parts.push(geminiFunctionCallPartFromAssistantResponse(r, replayThoughtSignature));
18345
+ }
18346
+ if (r.type === 'node') {
18347
+ parts.push({
18348
+ text: JSON.stringify({ type: 'node', content: r.content }),
18349
+ });
18350
+ }
18351
+ }
18352
+ }
18353
+ if (parts.length === 0) {
18354
+ parts.push({ text: '' });
18355
+ }
18356
+ return { role: 'model', parts };
18357
+ }
18358
+ function platformTranscriptToGeminiContents(messages, imageCache) {
18359
+ const currentTurnStart = findGeminiCurrentTurnStartIndex(messages);
18360
+ const out = [];
18361
+ let i = 0;
18362
+ while (i < messages.length) {
18363
+ const m = messages[i];
18364
+ if (m.role === 'assistant') {
18365
+ const groupStartIndex = i;
18366
+ const group = [];
18367
+ while (i < messages.length && messages[i].role === 'assistant') {
18368
+ group.push(messages[i]);
18369
+ i += 1;
18370
+ }
18371
+ out.push(assistantGroupToGeminiContent(group, groupStartIndex >= currentTurnStart));
18372
+ continue;
18373
+ }
18374
+ out.push(mapPlatformMessageToGeminiContent(m, imageCache));
18375
+ i += 1;
18376
+ }
18377
+ return out;
17895
18378
  }
17896
18379
  function appendGeminiUserResponsePart(r, parts, imageCache) {
17897
18380
  if (r.type === 'text') {
@@ -17906,13 +18389,9 @@ function appendGeminiUserResponsePart(r, parts, imageCache) {
17906
18389
  throw new Error(`Could not resolve chat file for Gemini request (fileId: ${id}).`);
17907
18390
  }
17908
18391
  const mime = resolved.mimeType.trim().toLowerCase();
17909
- const rawName = r.content.name?.trim();
17910
- const displayName = rawName && rawName.length > 0 ? rawName : undefined;
17911
18392
  if (mime.startsWith('audio/')) {
17912
18393
  parts.push({
17913
- text: displayName
17914
- ? `[Audio attachment: fileId=${id} name=${displayName}]`
17915
- : `[Audio attachment: fileId=${id}]`,
18394
+ text: `[Audio attachment: fileId=${id}]`,
17916
18395
  });
17917
18396
  return;
17918
18397
  }
@@ -17967,13 +18446,7 @@ function mapPlatformMessageToGeminiContent(message, imageCache) {
17967
18446
  parts.push({ text: `<think>${r.content}</think>` });
17968
18447
  }
17969
18448
  if (r.type === 'tool' || r.type === 'agent') {
17970
- const tc = r.content;
17971
- parts.push({
17972
- functionCall: {
17973
- name: toGeminiFunctionDeclarationName(tc.command),
17974
- args: geminiStructuredArgsFromToolArguments(tc.arguments),
17975
- },
17976
- });
18449
+ parts.push(geminiFunctionCallPartFromAssistantResponse(r, false));
17977
18450
  }
17978
18451
  if (r.type === 'node') {
17979
18452
  parts.push({
@@ -18004,16 +18477,7 @@ function mapPlatformMessageToGeminiContent(message, imageCache) {
18004
18477
  : r0?.type === 'file'
18005
18478
  ? (() => {
18006
18479
  const id = r0.content.fileId.trim();
18007
- const name = r0.content.name?.trim();
18008
- const mime = r0.content.mimeType?.trim().toLowerCase() ?? '';
18009
- if (mime.startsWith('audio/')) {
18010
- return name
18011
- ? `[Audio attachment: fileId=${id} name=${name}]`
18012
- : `[Audio attachment: fileId=${id}]`;
18013
- }
18014
- return name
18015
- ? `[File attachment: fileId=${id} name=${name}]`
18016
- : `[File attachment: fileId=${id}]`;
18480
+ return `[File attachment: fileId=${id}]`;
18017
18481
  })()
18018
18482
  : '';
18019
18483
  return {
@@ -18458,8 +18922,14 @@ function buildDemisChatRequestBody(args) {
18458
18922
  }
18459
18923
  function demisRawResponse(stream, chunks, demisSessionUuid) {
18460
18924
  const session = demisSessionUuid?.trim();
18925
+ if (stream) {
18926
+ return {
18927
+ stream: true,
18928
+ ...(session ? { demisSessionUuid: session } : {}),
18929
+ };
18930
+ }
18461
18931
  return {
18462
- stream,
18932
+ stream: false,
18463
18933
  chunks,
18464
18934
  ...(session ? { demisSessionUuid: session } : {}),
18465
18935
  };
@@ -18722,14 +19192,36 @@ class AXCAiChatDemisProvider {
18722
19192
  //#endregion
18723
19193
  //#region ---- Resolvers ----
18724
19194
  async preprocessAudioAttachments(messages, options) {
18725
- const hasAudio = messages.some((m) => m.role === 'user' &&
18726
- m.responses.some((r) => r.type === 'file' && r.content.mimeType?.trim().toLowerCase().startsWith('audio/')));
19195
+ let hasAudio = false;
19196
+ for (const m of messages) {
19197
+ if (m.role !== 'user') {
19198
+ continue;
19199
+ }
19200
+ for (const r of m.responses) {
19201
+ if (r.type !== 'file') {
19202
+ continue;
19203
+ }
19204
+ const fileId = r.content.fileId?.trim();
19205
+ if (!fileId) {
19206
+ continue;
19207
+ }
19208
+ const info = await this.fileStorage.getInfo(fileId);
19209
+ const mime = (info.mimeType?.trim() || info.binary.type?.trim() || '').toLowerCase();
19210
+ if (mime.startsWith('audio/')) {
19211
+ hasAudio = true;
19212
+ break;
19213
+ }
19214
+ }
19215
+ if (hasAudio) {
19216
+ break;
19217
+ }
19218
+ }
18727
19219
  if (!hasAudio) {
18728
19220
  return messages;
18729
19221
  }
18730
19222
  const speechModelEntityId = options.demis?.speechModelEntityId?.trim();
18731
19223
  if (!speechModelEntityId) {
18732
- throw new Error('Demis chat requires a speech catalog model on the assist (speechModelId) to transcribe audio attachments.');
19224
+ throw new Error('Demis chat requires a speech catalog model on the speech-to-text delegated specialist row (delegatedAgents[].options.model) to transcribe audio attachments.');
18733
19225
  }
18734
19226
  const out = [];
18735
19227
  for (const m of messages) {
@@ -18739,23 +19231,28 @@ class AXCAiChatDemisProvider {
18739
19231
  }
18740
19232
  const newResponses = [];
18741
19233
  for (const r of m.responses) {
18742
- if (r.type === 'file' && r.content.mimeType?.trim().toLowerCase().startsWith('audio/')) {
19234
+ if (r.type === 'file') {
18743
19235
  const fileId = r.content.fileId?.trim();
18744
19236
  if (!fileId) {
19237
+ newResponses.push(r);
18745
19238
  continue;
18746
19239
  }
18747
19240
  const info = await this.fileStorage.getInfo(fileId);
18748
- const audioBytes = await info.binary.arrayBuffer();
18749
19241
  const mimeType = info.mimeType?.trim() || info.binary.type?.trim() || 'application/octet-stream';
19242
+ if (!mimeType.toLowerCase().startsWith('audio/')) {
19243
+ newResponses.push(r);
19244
+ continue;
19245
+ }
19246
+ const audioBytes = await info.binary.arrayBuffer();
19247
+ const fileName = info.name?.trim() || info.binary.name?.trim() || undefined;
18750
19248
  const { text } = await this.transcribeSpeech({
18751
19249
  modelEntityId: speechModelEntityId,
18752
19250
  audioBytes,
18753
19251
  mimeType,
18754
- fileName: r.content.name,
19252
+ fileName,
18755
19253
  language: options.demis?.transcribeLanguage,
18756
19254
  });
18757
- const name = r.content.name?.trim();
18758
- const prefix = name ? `[Voice: ${name}]\n` : '[Voice]\n';
19255
+ const prefix = fileName ? `[Voice: ${fileName}]\n` : '[Voice]\n';
18759
19256
  newResponses.push({ type: 'text', content: `${prefix}${text}` });
18760
19257
  }
18761
19258
  else {
@@ -18804,7 +19301,8 @@ class AXCAiChatDemisProvider {
18804
19301
  }
18805
19302
  const info = await this.fileStorage.getInfo(fileId);
18806
19303
  const file = info.binary;
18807
- const fileName = (r.content.name?.trim() || `attachment`).replace(/[^\w.\-()\s]+/g, '_').trim() || 'attachment';
19304
+ const fileName = (info.name?.trim() || file.name?.trim() || 'attachment').replace(/[^\w.\-()\s]+/g, '_').trim() ||
19305
+ 'attachment';
18808
19306
  out.push({ file, fileName });
18809
19307
  }
18810
19308
  return out;
@@ -19060,52 +19558,98 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
19060
19558
 
19061
19559
  //#region ---- Imports ----
19062
19560
  //#endregion
19063
- //#region ---- System prompt formatting ----
19561
+ //#region ---- Helpers ----
19562
+ function hasContextValue(value) {
19563
+ return value != null && String(value).trim().length > 0;
19564
+ }
19565
+ function formatContextEntry(definition, rawValue) {
19566
+ const value = String(rawValue).trim();
19567
+ const label = definition.ai?.promptLabel ?? definition.title;
19568
+ const lines = [`- **${label}** (\`${definition.name}\`): ${value}`];
19569
+ if (definition.description?.trim()) {
19570
+ lines.push(` ${definition.description.trim()}`);
19571
+ }
19572
+ if (definition.ai?.usageHint?.trim()) {
19573
+ lines.push(` _Usage:_ ${definition.ai.usageHint.trim()}`);
19574
+ }
19575
+ return lines.join('\n');
19576
+ }
19577
+ //#endregion
19578
+ //#region ---- Definition-aware formatter ----
19064
19579
  /**
19065
- * Renders {@link AXPAiPlatformRuntimeContext} as an English system-prompt section for the LLM.
19066
- * Returns an empty string when {@link ctx} is nullish.
19580
+ * Builds an English system-prompt section from live values and registered {@link AXPContextDefinition} metadata.
19581
+ * Only keys with non-empty values are included. Definitions with `ai.includeInSystemPrompt === false` or
19582
+ * `ai.sensitive === true` are omitted.
19067
19583
  */
19068
- function formatPlatformRuntimeContextForSystemPrompt(ctx) {
19069
- if (!ctx) {
19584
+ function axcFormatContextForAiSystemPrompt(values, definitions) {
19585
+ const consumed = new Set();
19586
+ const blocks = [];
19587
+ const sortedDefinitions = [...definitions].sort((a, b) => (a.ai?.order ?? 999) - (b.ai?.order ?? 999) || a.name.localeCompare(b.name));
19588
+ for (const definition of sortedDefinitions) {
19589
+ if (definition.ai?.includeInSystemPrompt === false) {
19590
+ continue;
19591
+ }
19592
+ const raw = values[definition.name];
19593
+ if (!hasContextValue(raw)) {
19594
+ continue;
19595
+ }
19596
+ if (definition.ai?.sensitive) {
19597
+ continue;
19598
+ }
19599
+ consumed.add(definition.name);
19600
+ blocks.push({
19601
+ order: definition.ai?.order ?? 999,
19602
+ name: definition.name,
19603
+ text: formatContextEntry(definition, raw),
19604
+ });
19605
+ }
19606
+ for (const [name, raw] of Object.entries(values)) {
19607
+ if (consumed.has(name) || !hasContextValue(raw)) {
19608
+ continue;
19609
+ }
19610
+ blocks.push({
19611
+ order: 999,
19612
+ name,
19613
+ text: formatContextEntry({ name, title: name, description: '' }, raw),
19614
+ });
19615
+ }
19616
+ if (blocks.length === 0) {
19070
19617
  return '';
19071
19618
  }
19072
- const lines = [
19619
+ blocks.sort((a, b) => a.order - b.order || a.name.localeCompare(b.name));
19620
+ return [
19073
19621
  '## Platform runtime context',
19074
19622
  '',
19075
- 'Use the following values as defaults for dates, calendar interpretation, locale-aware explanations, and scope. Do not ask the user to confirm these defaults unless the request remains ambiguous after applying them (for example explicit cross-calendar comparison, or organization scope that cannot be inferred).',
19623
+ 'Use the following values as defaults. Each entry includes what the value means and how to apply it. Do not ask the user to confirm these defaults unless the request stays ambiguous after applying them.',
19076
19624
  '',
19077
- ];
19078
- const push = (label, value) => {
19079
- if (value != null && String(value).trim().length > 0) {
19080
- lines.push(`- ${label}: ${String(value).trim()}`);
19081
- }
19082
- };
19083
- push('User id', ctx.userId);
19084
- push('User display name', ctx.userDisplayName);
19085
- push('Tenant id', ctx.tenantId);
19086
- push('Tenant title', ctx.tenantTitle);
19087
- push('Application id', ctx.applicationId);
19088
- push('Application title', ctx.applicationTitle);
19089
- push('UI locale', ctx.locale);
19090
- push('Calendar system (regional setting)', ctx.calendarSystem);
19091
- push('Time zone (IANA)', ctx.timeZone);
19092
- push('Country (regional setting)', ctx.country);
19093
- push('Current instant (UTC, ISO 8601)', ctx.currentInstant);
19094
- push('Current local date/time (for interpretation)', ctx.currentLocalDateTime);
19095
- if (ctx.notes?.trim()) {
19096
- push('Notes', ctx.notes.trim());
19625
+ ...blocks.map((b) => b.text),
19626
+ ].join('\n');
19627
+ }
19628
+ //#endregion
19629
+ //#region ---- Append helper ----
19630
+ /** Appends a platform context block to a system prompt when non-empty. */
19631
+ function axcAppendContextBlockToSystemPrompt(base, block) {
19632
+ const trimmed = block?.trim();
19633
+ if (!trimmed) {
19634
+ return base;
19097
19635
  }
19098
- return lines.join('\n');
19636
+ return base.trim() ? `${base.trim()}\n\n${trimmed}` : trimmed;
19099
19637
  }
19638
+ //#endregion
19639
+
19640
+ //#region ---- Imports ----
19641
+ //#endregion
19642
+ //#region ---- Append (mock / backend only) ----
19100
19643
  /**
19101
- * Appends the platform runtime block to an existing system prompt when context is provided.
19644
+ * Appends platform runtime values plus {@link AXPContextDefinition} hints to a system prompt.
19645
+ * Not exposed on {@link AXPAiEngineRunOptions} — formatting stays in connectivity.
19102
19646
  */
19103
- function axpAiAppendPlatformRuntimeToSystem(base, ctx) {
19104
- const block = formatPlatformRuntimeContextForSystemPrompt(ctx);
19105
- if (!block) {
19647
+ async function axpAiAppendPlatformRuntimeToSystem(host, base, ctx) {
19648
+ if (!ctx || Object.keys(ctx).length === 0) {
19106
19649
  return base;
19107
19650
  }
19108
- return base.trim() ? `${base.trim()}\n\n${block}` : block;
19651
+ const block = await host.platformRuntimePrompt.format(ctx);
19652
+ return axcAppendContextBlockToSystemPrompt(base, block);
19109
19653
  }
19110
19654
  //#endregion
19111
19655
 
@@ -19459,16 +20003,16 @@ async function completeStructuredText(host, options) {
19459
20003
  }
19460
20004
  let messages = [...options.messages];
19461
20005
  const firstSystemIdx = messages.findIndex((m) => m.role === 'system');
19462
- if (options.platformRuntimeContext) {
20006
+ if (options.platformRuntimeContext && Object.keys(options.platformRuntimeContext).length > 0) {
19463
20007
  if (firstSystemIdx >= 0) {
19464
20008
  const text = axpAiChatMessageGetText(messages[firstSystemIdx]);
19465
- const merged = axpAiAppendPlatformRuntimeToSystem(text, options.platformRuntimeContext);
20009
+ const merged = await axpAiAppendPlatformRuntimeToSystem(host, text, options.platformRuntimeContext);
19466
20010
  messages = [...messages];
19467
20011
  messages[firstSystemIdx] = axpAiChatTextMessage('system', merged);
19468
20012
  }
19469
20013
  else {
19470
20014
  messages = [
19471
- axpAiChatTextMessage('system', axpAiAppendPlatformRuntimeToSystem('', options.platformRuntimeContext)),
20015
+ axpAiChatTextMessage('system', await axpAiAppendPlatformRuntimeToSystem(host, '', options.platformRuntimeContext)),
19472
20016
  ...messages,
19473
20017
  ];
19474
20018
  }
@@ -20072,8 +20616,8 @@ function axpAiBuildDelegatedSingleToolPolicyAddendum() {
20072
20616
  function axpAiBuildDelegatedToolReflectionAddendum() {
20073
20617
  return [
20074
20618
  '## Reflection turn (no tools)',
20075
- 'Reply in **one short plain-language sentence** (what succeeded or failed). **Never** paste tool JSON, `fileId`, mimeType, module/entity names, or storage identifiers.',
20076
- 'When the tool produced an image or file, the platform shows it automatically — say only that it is ready (e.g. “Your cartoon version is ready.”). No bullets unless another tool is still required.',
20619
+ 'Reply in **one short plain-language sentence** (what succeeded or failed). **Never** paste tool JSON, `fileId`, module/entity names, or storage identifiers.',
20620
+ 'When the tool produced an image or file, the platform shows it automatically — say only that it is ready (e.g. “Your cartoon version is ready.”). If the user asked for a **download**, ensure the file segment uses `"isDownloadable": true`. No bullets unless another tool is still required.',
20077
20621
  ].join('\n');
20078
20622
  }
20079
20623
  //#endregion
@@ -20178,8 +20722,9 @@ async function maybeAutoInvokeFollowUpAgent(host, supervisorAssist, allowedAgent
20178
20722
  };
20179
20723
  }
20180
20724
  async function executeAgentSubRun(host, supervisorAssist, agent, delegationCallId, rawArgs, transcriptMessages, options, chatProvider, usageTotals, tenantGlobalSystemPrompt) {
20725
+ const { includeRules: _parentIncludeRules, excludeRules: _parentExcludeRules, ...parentRunWithoutRules } = options;
20181
20726
  const subOptions = {
20182
- ...options,
20727
+ ...parentRunWithoutRules,
20183
20728
  ...(agent.modelEntityId?.trim() ? { modelEntityId: agent.modelEntityId.trim() } : {}),
20184
20729
  };
20185
20730
  const mergedSubOptions = {
@@ -20204,13 +20749,19 @@ async function executeAgentSubRun(host, supervisorAssist, agent, delegationCallI
20204
20749
  ? Math.min(Math.floor(agent.maxSteps), 50)
20205
20750
  : AXPAI_DELEGATED_AGENT_DEFAULT_MAX_STEPS;
20206
20751
  const coercedArgs = coerceAiToolArguments(rawArgs, axpAiSupervisorAgentToolName(agent.id?.trim() ?? 'delegate'));
20207
- const argsForMessage = resolveDelegatedAgentInvocationArgs({
20752
+ const mergedInvocationArgs = resolveDelegatedAgentInvocationArgs({
20208
20753
  supervisorArgs: coercedArgs,
20209
20754
  agent,
20210
20755
  assist: supervisorAssist,
20211
20756
  });
20757
+ const { args: specialistArgs, includeRules: delegatedIncludeRules, excludeRules: delegatedExcludeRules } = extractDelegatedInvocationRuleOverrides(mergedInvocationArgs);
20758
+ const delegatedRunOptions = {
20759
+ ...mergedSubOptions,
20760
+ ...(delegatedIncludeRules?.length ? { includeRules: delegatedIncludeRules } : {}),
20761
+ ...(delegatedExcludeRules?.length ? { excludeRules: delegatedExcludeRules } : {}),
20762
+ };
20212
20763
  let subMessages = [
20213
- axpAiChatTextMessage('user', buildAgentSubRunUserMessage(argsForMessage, transcriptMessages)),
20764
+ axpAiChatTextMessage('user', buildAgentSubRunUserMessage(specialistArgs, transcriptMessages)),
20214
20765
  ];
20215
20766
  const outputContract = await host.outputContractResolve.resolveEffective({
20216
20767
  runtime: options.outputContract,
@@ -20219,7 +20770,7 @@ async function executeAgentSubRun(host, supervisorAssist, agent, delegationCallI
20219
20770
  });
20220
20771
  const contractAddendum = buildAgentOutputContractSystemAddendum(outputContract);
20221
20772
  const responseFormat = deriveProviderResponseFormat(outputContract);
20222
- const rulesMarkdown = await resolveRulesMarkdownForRun(host, { rules: agent.rules, ruleIds: agent.ruleIds }, options);
20773
+ const rulesMarkdown = await resolveRulesMarkdownForRun(host, { rules: agent.rules, ruleIds: agent.ruleIds }, delegatedRunOptions);
20223
20774
  const agentCatalogPart = [
20224
20775
  agent.systemPrompt?.trim() ?? '',
20225
20776
  contractAddendum,
@@ -20233,7 +20784,7 @@ async function executeAgentSubRun(host, supervisorAssist, agent, delegationCallI
20233
20784
  rulesMarkdown,
20234
20785
  });
20235
20786
  let systemContent = appendSystemToolsHintIfNeeded(delegatedBaseSystem, nestedToolSchemas.length);
20236
- systemContent = axpAiAppendPlatformRuntimeToSystem(systemContent, options.platformRuntimeContext);
20787
+ systemContent = await axpAiAppendPlatformRuntimeToSystem(host, systemContent, delegatedRunOptions.platformRuntimeContext);
20237
20788
  const prevCtx = host.chatToolRunContext.getContext();
20238
20789
  host.chatToolRunContext.setContext({
20239
20790
  assistId: supervisorAssist.id,
@@ -20440,7 +20991,11 @@ async function executeAgentSubRun(host, supervisorAssist, agent, delegationCallI
20440
20991
  host.chatToolRunContext.setContext(prevCtx);
20441
20992
  const id = delegationCallId?.trim() ?? '';
20442
20993
  if (id) {
20443
- saveDelegatedInternalSnapshot(host, id, { agentName: agent.name, messages: subMessages });
20994
+ saveDelegatedInternalSnapshot(host, id, {
20995
+ agentName: agent.name,
20996
+ messages: subMessages,
20997
+ runInput: axpBuildDelegatedAgentRunInputSnapshot(id, agent.id?.trim() ?? '', agent.name, specialistArgs, delegatedRunOptions),
20998
+ });
20444
20999
  }
20445
21000
  }
20446
21001
  }
@@ -20452,6 +21007,7 @@ function saveDelegatedInternalSnapshot(host, callId, entry) {
20452
21007
  const snapshot = {
20453
21008
  agentName: entry.agentName?.trim() || undefined,
20454
21009
  messages: cloneDelegatedInternalMessages(entry.messages),
21010
+ ...(entry.runInput ? { runInput: entry.runInput } : {}),
20455
21011
  };
20456
21012
  if (host.delegatedInternalByCallId.has(id)) {
20457
21013
  const prevIdx = host.delegatedInternalLruOrder.indexOf(id);
@@ -20492,12 +21048,57 @@ function snapshotDelegatedTranscripts(host) {
20492
21048
  out[id] = {
20493
21049
  agentName: entry.agentName,
20494
21050
  messages: cloneDelegatedInternalMessages(entry.messages),
21051
+ ...(entry.runInput ? { runInput: entry.runInput } : {}),
20495
21052
  };
20496
21053
  }
20497
21054
  return Object.keys(out).length > 0 ? out : undefined;
20498
21055
  }
20499
21056
  //#endregion
20500
21057
 
21058
+ //#region ---- Imports ----
21059
+ //#endregion
21060
+ //#region ---- Service ----
21061
+ /**
21062
+ * Mock engine: renders {@link AXPAiPlatformRuntimeContext} for LLM system prompts using
21063
+ * {@link AXPContextDefinition} catalog entries (value + title, description, usage hints).
21064
+ */
21065
+ class AXCAiPlatformRuntimeContextPromptService {
21066
+ constructor() {
21067
+ //#region ---- Services & Dependencies ----
21068
+ this.contextDefinitions = inject(AXPContextDefinitionProviderService);
21069
+ }
21070
+ //#endregion
21071
+ //#region ---- Public API ----
21072
+ async format(ctx) {
21073
+ if (!ctx) {
21074
+ return '';
21075
+ }
21076
+ const values = this.normalizeValues(ctx);
21077
+ if (Object.keys(values).length === 0) {
21078
+ return '';
21079
+ }
21080
+ const definitions = await this.contextDefinitions.items();
21081
+ return axcFormatContextForAiSystemPrompt(values, definitions);
21082
+ }
21083
+ //#endregion
21084
+ //#region ---- Private Methods ----
21085
+ normalizeValues(ctx) {
21086
+ const values = {};
21087
+ for (const [key, value] of Object.entries(ctx)) {
21088
+ if (value != null && String(value).trim().length > 0) {
21089
+ values[key] = value;
21090
+ }
21091
+ }
21092
+ return values;
21093
+ }
21094
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXCAiPlatformRuntimeContextPromptService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
21095
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXCAiPlatformRuntimeContextPromptService, providedIn: 'root' }); }
21096
+ }
21097
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXCAiPlatformRuntimeContextPromptService, decorators: [{
21098
+ type: Injectable,
21099
+ args: [{ providedIn: 'root' }]
21100
+ }] });
21101
+
20501
21102
  //#region ---- Imports ----
20502
21103
  //#endregion
20503
21104
  //#region ---- Run ----
@@ -20537,7 +21138,8 @@ async function runAiEngine(host, options) {
20537
21138
  runIncludeAgents: mergedOptions.includeAgents,
20538
21139
  runExcludeAgents: mergedOptions.excludeAgents,
20539
21140
  });
20540
- const useSupervisor = delegatedAgents.length > 0 && chatTransport !== 'demis';
21141
+ const isDemisTransport = chatTransport === 'demis';
21142
+ const useSupervisor = delegatedAgents.length > 0 && !isDemisTransport;
20541
21143
  const delegatedAgentsById = useSupervisor
20542
21144
  ? new Map(delegatedAgents
20543
21145
  .map((row) => {
@@ -20546,7 +21148,8 @@ async function runAiEngine(host, options) {
20546
21148
  })
20547
21149
  .filter((e) => e != null))
20548
21150
  : new Map();
20549
- if (assistConfiguredDelegatedAgents && !useSupervisor) {
21151
+ // Demis transport does not support tools or delegated-agent orchestration; degrade gracefully.
21152
+ if (assistConfiguredDelegatedAgents && !useSupervisor && !isDemisTransport) {
20550
21153
  throw new Error('This assist is configured for delegated agents (delegatedAgents[].agent), but no AiAgent rows were resolved. Check the AiAgent catalog and assist configuration.');
20551
21154
  }
20552
21155
  let toolSchemas;
@@ -20555,6 +21158,10 @@ async function runAiEngine(host, options) {
20555
21158
  if (useSupervisor) {
20556
21159
  toolSchemas = buildAgentToolSchemas(delegatedAgents);
20557
21160
  }
21161
+ else if (isDemisTransport) {
21162
+ // Demis provider throws when tools are present, so always run as plain chat for this transport.
21163
+ toolSchemas = [];
21164
+ }
20558
21165
  else {
20559
21166
  const bundle = await host.catalogTools.getToolSchemasBundleForAssist(host.noDelegatedAgentRegistryTools);
20560
21167
  toolSchemas = bundle.merged;
@@ -20572,7 +21179,7 @@ async function runAiEngine(host, options) {
20572
21179
  : axpAiBuildPlanningAddendumGrouped(commandToolSchemasForPlanning, queryToolSchemasForPlanning, true);
20573
21180
  const basePrompt = axcAiMergeLayeredSystemPrompt(tenantGlobalSystemPrompt, assist.systemPrompt?.trim() ?? '', { role: 'assist', rulesMarkdown });
20574
21181
  let planningSystemContent = basePrompt ? `${basePrompt}\n\n${planningAddendum}` : planningAddendum;
20575
- planningSystemContent = axpAiAppendPlatformRuntimeToSystem(planningSystemContent, options.platformRuntimeContext);
21182
+ planningSystemContent = await axpAiAppendPlatformRuntimeToSystem(host, planningSystemContent, options.platformRuntimeContext);
20576
21183
  options.onRunEvent?.({ type: 'assistant_stream_reset' });
20577
21184
  const planningMessages = planningSystemContent.trim()
20578
21185
  ? [{ role: 'system', responses: [{ type: 'text', content: planningSystemContent }] }, ...messages]
@@ -20612,11 +21219,12 @@ async function runAiEngine(host, options) {
20612
21219
  });
20613
21220
  if (useSupervisor) {
20614
21221
  baseSystem = appendSupervisorAgentDelegationHint(baseSystem);
21222
+ baseSystem = appendSupervisorDelegationCatalogHint(baseSystem, delegatedAgents);
20615
21223
  }
20616
21224
  let systemContent = appendSystemToolsHintIfNeeded(baseSystem, toolSchemas.length, {
20617
21225
  supervisorDelegatedAgents: useSupervisor,
20618
21226
  });
20619
- systemContent = axpAiAppendPlatformRuntimeToSystem(systemContent, options.platformRuntimeContext);
21227
+ systemContent = await axpAiAppendPlatformRuntimeToSystem(host, systemContent, options.platformRuntimeContext);
20620
21228
  for (let step = 0; step < maxSteps; step++) {
20621
21229
  options.onRunEvent?.({ type: 'assistant_stream_reset' });
20622
21230
  const transcriptForProvider = [...messages];
@@ -20691,7 +21299,7 @@ async function runAiEngine(host, options) {
20691
21299
  }
20692
21300
  return {
20693
21301
  messages,
20694
- lastProviderResult,
21302
+ lastProviderResult: axpSanitizeLastProviderPayloadForPersistence(lastProviderResult),
20695
21303
  usageTotals,
20696
21304
  delegatedTranscriptsByCallId: snapshotDelegatedTranscripts(host),
20697
21305
  };
@@ -20757,7 +21365,7 @@ async function runDirectAgentChat(host, options, chatProvider, directAgentId) {
20757
21365
  const planningAddendum = axpAiBuildPlanningAddendumGrouped(commandToolSchemasForPlanning, queryToolSchemasForPlanning, true);
20758
21366
  const basePrompt = axcAiMergeLayeredSystemPrompt(tenantGlobalSystemPrompt, agent.systemPrompt?.trim() ?? '', { role: 'agent', rulesMarkdown });
20759
21367
  let planningSystemContent = basePrompt ? `${basePrompt}\n\n${planningAddendum}` : planningAddendum;
20760
- planningSystemContent = axpAiAppendPlatformRuntimeToSystem(planningSystemContent, options.platformRuntimeContext);
21368
+ planningSystemContent = await axpAiAppendPlatformRuntimeToSystem(host, planningSystemContent, options.platformRuntimeContext);
20761
21369
  options.onRunEvent?.({ type: 'assistant_stream_reset' });
20762
21370
  const planningMessages = planningSystemContent.trim()
20763
21371
  ? [{ role: 'system', responses: [{ type: 'text', content: planningSystemContent }] }, ...messages]
@@ -20800,7 +21408,7 @@ async function runDirectAgentChat(host, options, chatProvider, directAgentId) {
20800
21408
  rulesMarkdown,
20801
21409
  });
20802
21410
  let systemContent = appendSystemToolsHintIfNeeded(baseSystem, toolSchemas.length);
20803
- systemContent = axpAiAppendPlatformRuntimeToSystem(systemContent, options.platformRuntimeContext);
21411
+ systemContent = await axpAiAppendPlatformRuntimeToSystem(host, systemContent, options.platformRuntimeContext);
20804
21412
  const responseFormat = deriveProviderResponseFormat(effectiveOutputContract);
20805
21413
  for (let step = 0; step < maxSteps; step++) {
20806
21414
  options.onRunEvent?.({ type: 'assistant_stream_reset' });
@@ -20876,7 +21484,7 @@ async function runDirectAgentChat(host, options, chatProvider, directAgentId) {
20876
21484
  messages = finalized.messages;
20877
21485
  return {
20878
21486
  messages,
20879
- lastProviderResult,
21487
+ lastProviderResult: axpSanitizeLastProviderPayloadForPersistence(lastProviderResult),
20880
21488
  usageTotals,
20881
21489
  delegatedTranscriptsByCallId: snapshotDelegatedTranscripts(host),
20882
21490
  };
@@ -20904,6 +21512,7 @@ class AXCAiEngine extends AXPAiEngine {
20904
21512
  this.chatToolRunContext = inject(AXPAiChatToolRunContextService);
20905
21513
  this.aiChatRouter = inject(AXCAiChatRouterService);
20906
21514
  this.outputContractResolve = inject(AXPAiOutputContractResolveService);
21515
+ this.platformRuntimePrompt = inject(AXCAiPlatformRuntimeContextPromptService);
20907
21516
  this.delegatedInternalByCallId = new Map();
20908
21517
  this.delegatedInternalLruOrder = [];
20909
21518
  this.entityService = inject(AXPEntityService);
@@ -21043,6 +21652,113 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
21043
21652
  type: Injectable
21044
21653
  }] });
21045
21654
 
21655
+ //#region ---- Imports ----
21656
+ //#endregion
21657
+ const M$19 = createMultiLanguageString;
21658
+ //#region ---- Stable ids ----
21659
+ const AXMAiRuleMarkdownId = 'd0000001-0000-4000-8000-000000000001';
21660
+ /** Programmatic rule name for user-visible Markdown formatting. */
21661
+ const AXMAiRuleMarkdownName = 'markdown';
21662
+ const AXMAiRuleWorkflowNarrationId = 'd0000002-0000-4000-8000-000000000002';
21663
+ /** Programmatic rule name for brief before/after step narration in conversation chat. */
21664
+ const AXMAiRuleWorkflowNarrationName = 'workflow-narration';
21665
+ const AXMAiRuleEndUserLanguageId = 'd0000003-0000-4000-8000-000000000003';
21666
+ /** Programmatic rule name for non-technical, end-user-friendly assistant copy in conversation chat. */
21667
+ const AXMAiRuleEndUserLanguageName = 'end-user-language';
21668
+ //#endregion
21669
+ //#region ---- Default markdown rule body ----
21670
+ /** Former {@link AXC_AI_ASSIST_SYSTEM_PROMPT} baseline — now catalog-managed. */
21671
+ const AXC_AI_MARKDOWN_RULE_BODY = [
21672
+ '## Response format (user-visible text)',
21673
+ '- **Always use Markdown** in plain-text replies to the user (not in tool JSON). Prefer rich structure over flat paragraphs.',
21674
+ '- **Headings**: use `##` / `###` to separate topics; keep a short lead line under each heading.',
21675
+ '- **Emphasis**: use **bold** for key terms, numbers, names, and conclusions; use *italic* sparingly for nuance.',
21676
+ '- **Lists**: use bullet lists for unordered items and numbered lists for steps, rankings, or sequences.',
21677
+ '- **Tables**: use Markdown tables when comparing columns or showing multiple entities with the same fields.',
21678
+ '- **Code**: wrap identifiers, paths, keys, and short snippets in `inline code`; use fenced code blocks only when showing multi-line examples.',
21679
+ '- **Links**: use `[label](url)` when citing URLs; do not paste bare long URLs without a label.',
21680
+ '- **Density**: break long answers into scannable sections; avoid walls of text — one idea per bullet when listing facts.',
21681
+ '- **Charts / layout envelopes**: when the UI renders structured output, still add a brief Markdown summary (bullets + **bold** highlights) above or beside it.',
21682
+ ].join('\n');
21683
+ /** Conversation assist: short progress beats before/after tools and delegated agents. */
21684
+ const AXC_AI_WORKFLOW_NARRATION_RULE_BODY = [
21685
+ '## Workflow narration (keep the user in the loop)',
21686
+ '- For **multi-step** work (platform lookup, delegated specialists, mutations, layout builds), narrate progress in **user-visible** assistant text — not inside tool JSON.',
21687
+ '- **Before** each substantive step (tool call or delegated specialist): **1–2 short sentences** in **plain language** — what you will do next (e.g. “Let me find where user registration is in the app.”).',
21688
+ '- **After** each step returns: **1–2 short sentences** — what you learned in user terms, then what you will do next (e.g. “I found the registration screen fields. Next I’ll draft the form layout.”).',
21689
+ '- Match the user’s language (Persian or English). Use Markdown from the `markdown` rule for structure.',
21690
+ '- Keep each beat **brief**; narration is for orientation, not long essays. Skip narration only for trivial one-line replies (greetings, thanks, single fact with no tools).',
21691
+ '- Do **not** repeat the same beat twice. Do **not** hide tool/agent work — the user should be able to follow the thread without reading raw tool payloads.',
21692
+ '',
21693
+ '### Example (user: “Build a user registration form”)',
21694
+ '1. *Before lookup:* “I’ll check how user registration is set up in the app.”',
21695
+ '2. *After lookup:* “I found the registration fields — next I’ll build the form layout.”',
21696
+ '3. *After layout:* “Here is the registration form …” (then deliver the layout / summary as usual).',
21697
+ ].join('\n');
21698
+ /** Conversation assist: plain language for non-technical end users. */
21699
+ const AXC_AI_END_USER_LANGUAGE_RULE_BODY = [
21700
+ '## End-user language (no technical jargon)',
21701
+ '- The reader is an **end user**, not a developer or admin. Write as a helpful product guide, not an internal runbook.',
21702
+ '- **Never** expose in user-visible text: module names, `Module.Entity` keys, registry/command/query names, agent or specialist ids, `fileId`, UUIDs, JSON tool payloads, chart/widget construction steps, datasource names, or “how the platform built” something.',
21703
+ '- **Navigation**: describe where to click using **menu labels and breadcrumbs** the user sees — not internal entity keys or API identifiers.',
21704
+ '- **Charts / forms / layouts**: show the result (chart, form, image) via structured UI segments when available; summarize in plain language (“Here is the sales chart for last month.”) — do not explain widget trees, block-layout, or validation commands.',
21705
+ '- **Images / files**: the UI renders them automatically. Confirm with one short sentence only; do not paste file metadata or JSON.',
21706
+ '- **When something fails**: one clear sentence in everyday language and what the user can try next — no stack traces, error codes, or tool names unless the user explicitly asks for technical detail.',
21707
+ '- Match the user’s language (Persian or English). Keep Markdown from the `markdown` rule when it helps scannability.',
21708
+ ].join('\n');
21709
+ //#endregion
21710
+ //#region ---- Mock helpers ----
21711
+ /** Builds multi-lookup storage (`ruleIds` + denormalized `rules`) for assist/agent mocks. */
21712
+ function axcAiRuleRefsByIds(...ids) {
21713
+ const rules = [];
21714
+ for (const raw of ids) {
21715
+ const id = raw.trim();
21716
+ if (!id) {
21717
+ continue;
21718
+ }
21719
+ const row = AI_RULE_MOCK.find((r) => r.id === id);
21720
+ if (!row) {
21721
+ continue;
21722
+ }
21723
+ rules.push({ id: row.id, name: row.name, title: row.title });
21724
+ }
21725
+ return { ruleIds: rules.map((r) => r.id), rules };
21726
+ }
21727
+ /** Mock helper: resolve catalog rows by programmatic `name`, persist as `ruleIds`. */
21728
+ function axcAiRuleRefsByNames(...names) {
21729
+ const ids = names
21730
+ .map((n) => n.trim())
21731
+ .map((name) => AI_RULE_MOCK.find((r) => r.name === name)?.id)
21732
+ .filter((id) => !!id);
21733
+ return axcAiRuleRefsByIds(...ids);
21734
+ }
21735
+ //#endregion
21736
+ //#region ---- Mock rows ----
21737
+ const AI_RULE_MOCK = [
21738
+ {
21739
+ id: AXMAiRuleMarkdownId,
21740
+ name: AXMAiRuleMarkdownName,
21741
+ title: M$19('Markdown replies', 'پاسخ‌های Markdown'),
21742
+ description: M$19('Format user-visible assistant text with headings, lists, tables, and emphasis.', 'قالب‌بندی متن قابل‌مشاهده برای کاربر با عنوان، فهرست، جدول و تأکید.'),
21743
+ markdown: AXC_AI_MARKDOWN_RULE_BODY,
21744
+ },
21745
+ {
21746
+ id: AXMAiRuleWorkflowNarrationId,
21747
+ name: AXMAiRuleWorkflowNarrationName,
21748
+ title: M$19('Workflow narration', 'روایت گام‌های کار'),
21749
+ description: M$19('Brief before/after explanations for each tool or specialist step so the user can follow progress.', 'توضیح کوتاه قبل و بعد از هر ابزار یا متخصص تا کاربر روند کار را دنبال کند.'),
21750
+ markdown: AXC_AI_WORKFLOW_NARRATION_RULE_BODY,
21751
+ },
21752
+ {
21753
+ id: AXMAiRuleEndUserLanguageId,
21754
+ name: AXMAiRuleEndUserLanguageName,
21755
+ title: M$19('End-user language', 'زبان کاربر نهایی'),
21756
+ description: M$19('Plain, non-technical replies for conversation chat — no module names, tool ids, or implementation details.', 'پاسخ ساده و غیرفنی در چت مکالمه — بدون نام ماژول، شناسه ابزار یا جزئیات پیاده‌سازی.'),
21757
+ markdown: AXC_AI_END_USER_LANGUAGE_RULE_BODY,
21758
+ },
21759
+ ];
21760
+ //#endregion
21761
+
21046
21762
  //#region ---- Imports ----
21047
21763
  //#endregion
21048
21764
  //#region ---- Rule seeder ----
@@ -21257,7 +21973,7 @@ class AXCAiManagementMockModule {
21257
21973
  provideCommandSetups([
21258
21974
  {
21259
21975
  key: 'AiManagement:ChatGenerateImage',
21260
- command: () => import('./acorex-connectivity-mock-chat-generate-image.command-CzaHjSnU.mjs').then((c) => c.AiManagementChatGenerateImageCommand),
21976
+ command: () => import('./acorex-connectivity-mock-chat-generate-image.command-D6J0xCjZ.mjs').then((c) => c.AiManagementChatGenerateImageCommand),
21261
21977
  },
21262
21978
  {
21263
21979
  key: 'AiManagement:ExtractDocumentText',
@@ -21269,11 +21985,11 @@ class AXCAiManagementMockModule {
21269
21985
  },
21270
21986
  {
21271
21987
  key: 'AiManagement:ChatTranscribeSpeech',
21272
- command: () => import('./acorex-connectivity-mock-chat-transcribe-speech.command-B1v1x3zx.mjs').then((c) => c.AiManagementChatTranscribeSpeechCommand),
21988
+ command: () => import('./acorex-connectivity-mock-chat-transcribe-speech.command-D_mclluL.mjs').then((c) => c.AiManagementChatTranscribeSpeechCommand),
21273
21989
  },
21274
21990
  {
21275
21991
  key: 'AiManagement:ChatSynthesizeSpeech',
21276
- command: () => import('./acorex-connectivity-mock-chat-synthesize-speech.command-P5gOvT0K.mjs').then((c) => c.AiManagementChatSynthesizeSpeechCommand),
21992
+ command: () => import('./acorex-connectivity-mock-chat-synthesize-speech.command-D66e7J-F.mjs').then((c) => c.AiManagementChatSynthesizeSpeechCommand),
21277
21993
  },
21278
21994
  ]),
21279
21995
  ] }); }
@@ -21326,7 +22042,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
21326
22042
  provideCommandSetups([
21327
22043
  {
21328
22044
  key: 'AiManagement:ChatGenerateImage',
21329
- command: () => import('./acorex-connectivity-mock-chat-generate-image.command-CzaHjSnU.mjs').then((c) => c.AiManagementChatGenerateImageCommand),
22045
+ command: () => import('./acorex-connectivity-mock-chat-generate-image.command-D6J0xCjZ.mjs').then((c) => c.AiManagementChatGenerateImageCommand),
21330
22046
  },
21331
22047
  {
21332
22048
  key: 'AiManagement:ExtractDocumentText',
@@ -21338,11 +22054,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
21338
22054
  },
21339
22055
  {
21340
22056
  key: 'AiManagement:ChatTranscribeSpeech',
21341
- command: () => import('./acorex-connectivity-mock-chat-transcribe-speech.command-B1v1x3zx.mjs').then((c) => c.AiManagementChatTranscribeSpeechCommand),
22057
+ command: () => import('./acorex-connectivity-mock-chat-transcribe-speech.command-D_mclluL.mjs').then((c) => c.AiManagementChatTranscribeSpeechCommand),
21342
22058
  },
21343
22059
  {
21344
22060
  key: 'AiManagement:ChatSynthesizeSpeech',
21345
- command: () => import('./acorex-connectivity-mock-chat-synthesize-speech.command-P5gOvT0K.mjs').then((c) => c.AiManagementChatSynthesizeSpeechCommand),
22061
+ command: () => import('./acorex-connectivity-mock-chat-synthesize-speech.command-D66e7J-F.mjs').then((c) => c.AiManagementChatSynthesizeSpeechCommand),
21346
22062
  },
21347
22063
  ]),
21348
22064
  ],
@@ -22697,8 +23413,8 @@ const textAreaInterface = {
22697
23413
  rows: 3,
22698
23414
  },
22699
23415
  };
22700
- const fileUploaderInterface = {
22701
- type: 'file-uploader',
23416
+ const attachmentsInterface = {
23417
+ type: 'attachments',
22702
23418
  options: {
22703
23419
  accept: [],
22704
23420
  multiple: true,
@@ -27142,9 +27858,7 @@ const collectMaintenanceTypeIds = (category, allCategories) => {
27142
27858
  if (current.maintenanceTypeIds?.length) {
27143
27859
  current.maintenanceTypeIds.forEach((id) => ids.add(id));
27144
27860
  }
27145
- current = current.parentId
27146
- ? allCategories.find((c) => c.id === current.parentId)
27147
- : null;
27861
+ current = current.parentId ? allCategories.find((c) => c.id === current.parentId) : null;
27148
27862
  }
27149
27863
  return [...ids];
27150
27864
  };
@@ -27156,9 +27870,7 @@ const checkHasMaintenance = (category, allCategories) => {
27156
27870
  while (current) {
27157
27871
  if (current.hasMaintenance === true)
27158
27872
  return true;
27159
- current = current.parentId
27160
- ? allCategories.find((c) => c.id === current.parentId)
27161
- : null;
27873
+ current = current.parentId ? allCategories.find((c) => c.id === current.parentId) : null;
27162
27874
  }
27163
27875
  return false;
27164
27876
  };
@@ -27213,10 +27925,12 @@ const enrichAsset = async (asset, backend) => {
27213
27925
  const result = await backend.query(CATEGORY_ENTITY, { skip: 0, take: 1000 });
27214
27926
  const allCategories = result?.items ?? [];
27215
27927
  const matchingCategories = allCategories.filter((c) => asset.categoryIds.includes(c.id));
27216
- const availableMaintenanceTypeIds = [...new Set([
27928
+ const availableMaintenanceTypeIds = [
27929
+ ...new Set([
27217
27930
  ...assetTypeMaintenanceTypeIds,
27218
27931
  ...matchingCategories.flatMap((c) => collectMaintenanceTypeIds(c, allCategories)),
27219
- ])];
27932
+ ]),
27933
+ ];
27220
27934
  return { ...enrichedAsset, hasMaintenance: explicitHasMaintenance, availableMaintenanceTypeIds };
27221
27935
  }
27222
27936
  catch {
@@ -27249,10 +27963,12 @@ const enrichAsset = async (asset, backend) => {
27249
27963
  const hasMaintenanceByCategory = matchingCategories.some((c) => checkHasMaintenance(c, allCategories));
27250
27964
  const hasMaintenance = assetTypeHasMaintenance || hasMaintenanceByCategory;
27251
27965
  // Aggregate maintenanceTypeIds from all matching categories (including parent hierarchy)
27252
- const availableMaintenanceTypeIds = [...new Set([
27966
+ const availableMaintenanceTypeIds = [
27967
+ ...new Set([
27253
27968
  ...assetTypeMaintenanceTypeIds,
27254
27969
  ...matchingCategories.flatMap((c) => collectMaintenanceTypeIds(c, allCategories)),
27255
- ])];
27970
+ ]),
27971
+ ];
27256
27972
  return { ...enrichedAsset, hasMaintenance, availableMaintenanceTypeIds };
27257
27973
  }
27258
27974
  catch {
@@ -40701,94 +41417,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
40701
41417
  type: Injectable
40702
41418
  }] });
40703
41419
 
40704
- //#region ---- Imports ----
40705
- //#endregion
40706
- //#region ---- Upload helpers ----
40707
- const DEFAULT_MIME = 'application/octet-stream';
40708
- /** Strips parameters from MIME (e.g. `audio/webm;codecs=opus` → `audio/webm`). */
40709
- function axcNormalizeMimeType(mime) {
40710
- const trimmed = trim(mime);
40711
- if (!trimmed) {
40712
- return DEFAULT_MIME;
40713
- }
40714
- return trimmed.split(';')[0]?.trim() || DEFAULT_MIME;
40715
- }
40716
- /** Whisper-friendly extension for a normalized audio MIME type. */
40717
- function axcAudioExtensionForMime(mime) {
40718
- const normalized = axcNormalizeMimeType(mime).toLowerCase();
40719
- if (normalized.includes('webm')) {
40720
- return 'webm';
40721
- }
40722
- if (normalized.includes('wav')) {
40723
- return 'wav';
40724
- }
40725
- if (normalized.includes('ogg') || normalized.includes('oga')) {
40726
- return 'ogg';
40727
- }
40728
- if (normalized.includes('mpeg') || normalized.includes('mp3')) {
40729
- return 'mp3';
40730
- }
40731
- if (normalized.includes('m4a') || normalized.includes('mp4')) {
40732
- return 'm4a';
40733
- }
40734
- if (normalized.includes('flac')) {
40735
- return 'flac';
40736
- }
40737
- return 'webm';
40738
- }
40739
- /** Ensures stored chat audio has a filename extension OpenAI / Demis can detect. */
40740
- function axcEnsureAudioFileName(fileName, mime) {
40741
- const base = trim(fileName) || 'audio';
40742
- if (/\.[a-z0-9]+$/i.test(base)) {
40743
- return base;
40744
- }
40745
- return `${base}.${axcAudioExtensionForMime(mime)}`;
40746
- }
40747
- /** Normalizes {@link AXUploaderRequest.source} to a {@link File} for persistence. */
40748
- function axcToUploadFile(request) {
40749
- const { source } = request;
40750
- const type = axcNormalizeMimeType(trim(request.mimeType) || source.type || DEFAULT_MIME);
40751
- let name = trim(request.fileName) || 'attachment';
40752
- if (type.startsWith('audio/')) {
40753
- name = axcEnsureAudioFileName(name, type);
40754
- }
40755
- if (source instanceof File) {
40756
- if (source.type === type && source.name === name) {
40757
- return source;
40758
- }
40759
- return new File([source], name, { type });
40760
- }
40761
- return new File([source], name, { type });
40762
- }
40763
- /** Resolves a platform file-storage record to a display/playback URL. */
40764
- function axcResolveFileStorageUrl(url, binary) {
40765
- const trimmed = trim(url);
40766
- if (trimmed) {
40767
- return trimmed;
40768
- }
40769
- if (binary instanceof Blob && binary.size > 0) {
40770
- return URL.createObjectURL(binary);
40771
- }
40772
- return '';
40773
- }
40774
- /**
40775
- * Builds an {@link AXUploaderResult} after mock persistence.
40776
- * conversation2 pickers require a truthy `url` before send.
40777
- */
40778
- async function axcBuildMockUploadResult(file, fileId, toDataUrl, metadata) {
40779
- const url = await toDataUrl(file);
40780
- const mimeType = axcNormalizeMimeType(defaultTo(trim(file.type), DEFAULT_MIME));
40781
- return {
40782
- url,
40783
- ...(mimeType.startsWith('image/') ? { thumbnailUrl: url } : {}),
40784
- mediaId: fileId,
40785
- size: file.size,
40786
- mimeType,
40787
- metadata,
40788
- };
40789
- }
40790
- //#endregion
40791
-
40792
41420
  //#region ---- Imports ----
40793
41421
  //#endregion
40794
41422
  //#region ---- Participants ----
@@ -40902,6 +41530,7 @@ class AXCConversationMockMessageApi extends AXMChatMessageApi {
40902
41530
  super(...arguments);
40903
41531
  //#region ---- Services & Dependencies ----
40904
41532
  this.aiEngine = inject(AXPAiEngine);
41533
+ this.platformRuntimeContextBuilder = inject(AXPAiPlatformRuntimeContextBuilder);
40905
41534
  this.modelCatalog = inject(AXPAiAssistChatModelCatalogService);
40906
41535
  this.aiResponder = inject(AXConversationAiResponderService);
40907
41536
  this.toastService = inject(AXToastService);
@@ -40917,6 +41546,12 @@ class AXCConversationMockMessageApi extends AXMChatMessageApi {
40917
41546
  .data();
40918
41547
  }
40919
41548
  //#endregion
41549
+ //#region ---- Platform runtime context ----
41550
+ /** Session / locale snapshot for assist engine runs (prompt assembly stays in mock AI engine). */
41551
+ async resolvePlatformRuntimeContextForRun() {
41552
+ return this.platformRuntimeContextBuilder.build();
41553
+ }
41554
+ //#endregion
40920
41555
  //#region ---- Message CRUD ----
40921
41556
  async sendMessage(command) {
40922
41557
  const currentUser = axcGetCurrentParticipant();
@@ -41466,6 +42101,7 @@ class AXCConversationMockMessageApi extends AXMChatMessageApi {
41466
42101
  modelEntityId,
41467
42102
  maxSteps: 1,
41468
42103
  messages: [axpAiChatTextMessage('user', titlePrompt)],
42104
+ platformRuntimeContext: await this.resolvePlatformRuntimeContextForRun(),
41469
42105
  });
41470
42106
  const candidate = this.extractLatestAssistantContent(runResult.messages);
41471
42107
  const normalizedTitle = this.normalizeConversationTitle(candidate);
@@ -41524,10 +42160,12 @@ class AXCConversationMockMessageApi extends AXMChatMessageApi {
41524
42160
  /** Context size sent into the engine; `run` appends only new assistant/tool lines after this. */
41525
42161
  const contextAiMessageCount = messages.length;
41526
42162
  const demisSessionUuid = await this.resolveDemisSessionUuidForConversation(conversationId, modelEntityId);
42163
+ const platformRuntimeContext = await this.resolvePlatformRuntimeContextForRun();
41527
42164
  const runResult = await this.aiEngine.run({
41528
42165
  ...(target.directAgentId ? { directAgentId: target.directAgentId } : { assistId: target.assistId }),
41529
42166
  messages,
41530
42167
  modelEntityId,
42168
+ platformRuntimeContext,
41531
42169
  ...(demisSessionUuid ? { demisSessionUuid } : {}),
41532
42170
  includeRules: [
41533
42171
  AXMAiRuleMarkdownName,
@@ -41577,7 +42215,6 @@ class AXCConversationMockMessageApi extends AXMChatMessageApi {
41577
42215
  }
41578
42216
  },
41579
42217
  });
41580
- console.log(runResult);
41581
42218
  let responseTranscript = runResult.messages.slice(contextAiMessageCount);
41582
42219
  let usageTotals = runResult.usageTotals;
41583
42220
  let demisPayloadTranscript;
@@ -41598,7 +42235,7 @@ class AXCConversationMockMessageApi extends AXMChatMessageApi {
41598
42235
  durationMs: Date.now() - runStartedAt,
41599
42236
  modelEntityId,
41600
42237
  modelTitle,
41601
- lastProviderResult: runResult.lastProviderResult,
42238
+ lastProviderResult: axpSanitizeLastProviderPayloadForPersistence(runResult.lastProviderResult),
41602
42239
  delegatedTranscriptsByCallId: runResult.delegatedTranscriptsByCallId,
41603
42240
  }, demisPayloadTranscript);
41604
42241
  }
@@ -41632,6 +42269,7 @@ class AXCConversationMockMessageApi extends AXMChatMessageApi {
41632
42269
  modelEntityId: AXMAiModelStableIds.demisAi,
41633
42270
  maxSteps: 1,
41634
42271
  messages: [axpAiChatTextMessage('user', followUpPrompt)],
42272
+ platformRuntimeContext: await this.resolvePlatformRuntimeContextForRun(),
41635
42273
  });
41636
42274
  const plain = this.extractLastAssistantPlainText(followUpResult.messages);
41637
42275
  const items = this.parseFollowUpSuggestionsFromDemisPlainText(plain);
@@ -42158,7 +42796,7 @@ class AXCConversationMockMessageApi extends AXMChatMessageApi {
42158
42796
  delete meta['assistRunModelTitle'];
42159
42797
  }
42160
42798
  if (runDebug.lastProviderResult) {
42161
- meta['assistRunLastProviderResult'] = runDebug.lastProviderResult;
42799
+ meta['assistRunLastProviderResult'] = axpSanitizeLastProviderPayloadForPersistence(runDebug.lastProviderResult);
42162
42800
  }
42163
42801
  else {
42164
42802
  delete meta['assistRunLastProviderResult'];
@@ -42349,7 +42987,7 @@ class AXCConversationMockMessageApi extends AXMChatMessageApi {
42349
42987
  }
42350
42988
  /**
42351
42989
  * Maps a stored conversation message to a platform {@link AXPAiChatMessage}.
42352
- * User image/file lines use `fileId` + `mimeType` so providers resolve bytes from file storage.
42990
+ * User image/file lines use `fileId` so providers resolve bytes from file storage.
42353
42991
  */
42354
42992
  conversationMessageToAiChatMessage(message, assistParticipantId) {
42355
42993
  const role = message.senderId === assistParticipantId ? 'assistant' : 'user';
@@ -42378,10 +43016,9 @@ class AXCConversationMockMessageApi extends AXMChatMessageApi {
42378
43016
  if (!fileId) {
42379
43017
  continue;
42380
43018
  }
42381
- const mimeType = trim(image.mimeType) || 'image/jpeg';
42382
43019
  out.push({
42383
43020
  type: 'file',
42384
- content: { fileId, mimeType },
43021
+ content: { fileId },
42385
43022
  });
42386
43023
  }
42387
43024
  return out;
@@ -42394,11 +43031,9 @@ class AXCConversationMockMessageApi extends AXMChatMessageApi {
42394
43031
  if (!fileId) {
42395
43032
  continue;
42396
43033
  }
42397
- const mimeType = trim(file.mimeType) || 'application/octet-stream';
42398
- const name = trim(file.name);
42399
43034
  out.push({
42400
43035
  type: 'file',
42401
- content: { fileId, mimeType, ...(name ? { name } : {}) },
43036
+ content: { fileId },
42402
43037
  });
42403
43038
  }
42404
43039
  return out;
@@ -42411,20 +43046,14 @@ class AXCConversationMockMessageApi extends AXMChatMessageApi {
42411
43046
  /** Maps voice / audio payloads (`mediaId`) to platform `file` responses for the AI engine. */
42412
43047
  extractUserVoiceOrAudioFileResponses(message) {
42413
43048
  const out = [];
42414
- const pushAudio = (fileId, mimeType, name) => {
43049
+ const pushAudio = (fileId, _mimeType, _name) => {
42415
43050
  const id = trim(fileId);
42416
43051
  if (!id) {
42417
43052
  return;
42418
43053
  }
42419
- const mime = axcNormalizeMimeType(mimeType || 'audio/webm');
42420
- const label = axcEnsureAudioFileName(trim(name), mime);
42421
43054
  out.push({
42422
43055
  type: 'file',
42423
- content: {
42424
- fileId: id,
42425
- mimeType: mime,
42426
- name: label,
42427
- },
43056
+ content: { fileId: id },
42428
43057
  });
42429
43058
  };
42430
43059
  if (message.type === 'voice') {
@@ -42885,6 +43514,94 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
42885
43514
  type: Injectable
42886
43515
  }] });
42887
43516
 
43517
+ //#region ---- Imports ----
43518
+ //#endregion
43519
+ //#region ---- Upload helpers ----
43520
+ const DEFAULT_MIME = 'application/octet-stream';
43521
+ /** Strips parameters from MIME (e.g. `audio/webm;codecs=opus` → `audio/webm`). */
43522
+ function axcNormalizeMimeType(mime) {
43523
+ const trimmed = trim(mime);
43524
+ if (!trimmed) {
43525
+ return DEFAULT_MIME;
43526
+ }
43527
+ return trimmed.split(';')[0]?.trim() || DEFAULT_MIME;
43528
+ }
43529
+ /** Whisper-friendly extension for a normalized audio MIME type. */
43530
+ function axcAudioExtensionForMime(mime) {
43531
+ const normalized = axcNormalizeMimeType(mime).toLowerCase();
43532
+ if (normalized.includes('webm')) {
43533
+ return 'webm';
43534
+ }
43535
+ if (normalized.includes('wav')) {
43536
+ return 'wav';
43537
+ }
43538
+ if (normalized.includes('ogg') || normalized.includes('oga')) {
43539
+ return 'ogg';
43540
+ }
43541
+ if (normalized.includes('mpeg') || normalized.includes('mp3')) {
43542
+ return 'mp3';
43543
+ }
43544
+ if (normalized.includes('m4a') || normalized.includes('mp4')) {
43545
+ return 'm4a';
43546
+ }
43547
+ if (normalized.includes('flac')) {
43548
+ return 'flac';
43549
+ }
43550
+ return 'webm';
43551
+ }
43552
+ /** Ensures stored chat audio has a filename extension OpenAI / Demis can detect. */
43553
+ function axcEnsureAudioFileName(fileName, mime) {
43554
+ const base = trim(fileName) || 'audio';
43555
+ if (/\.[a-z0-9]+$/i.test(base)) {
43556
+ return base;
43557
+ }
43558
+ return `${base}.${axcAudioExtensionForMime(mime)}`;
43559
+ }
43560
+ /** Normalizes {@link AXUploaderRequest.source} to a {@link File} for persistence. */
43561
+ function axcToUploadFile(request) {
43562
+ const { source } = request;
43563
+ const type = axcNormalizeMimeType(trim(request.mimeType) || source.type || DEFAULT_MIME);
43564
+ let name = trim(request.fileName) || 'attachment';
43565
+ if (type.startsWith('audio/')) {
43566
+ name = axcEnsureAudioFileName(name, type);
43567
+ }
43568
+ if (source instanceof File) {
43569
+ if (source.type === type && source.name === name) {
43570
+ return source;
43571
+ }
43572
+ return new File([source], name, { type });
43573
+ }
43574
+ return new File([source], name, { type });
43575
+ }
43576
+ /** Resolves a platform file-storage record to a display/playback URL. */
43577
+ function axcResolveFileStorageUrl(url, binary) {
43578
+ const trimmed = trim(url);
43579
+ if (trimmed) {
43580
+ return trimmed;
43581
+ }
43582
+ if (binary instanceof Blob && binary.size > 0) {
43583
+ return URL.createObjectURL(binary);
43584
+ }
43585
+ return '';
43586
+ }
43587
+ /**
43588
+ * Builds an {@link AXUploaderResult} after mock persistence.
43589
+ * conversation2 pickers require a truthy `url` before send.
43590
+ */
43591
+ async function axcBuildMockUploadResult(file, fileId, toDataUrl, metadata) {
43592
+ const url = await toDataUrl(file);
43593
+ const mimeType = axcNormalizeMimeType(defaultTo(trim(file.type), DEFAULT_MIME));
43594
+ return {
43595
+ url,
43596
+ ...(mimeType.startsWith('image/') ? { thumbnailUrl: url } : {}),
43597
+ mediaId: fileId,
43598
+ size: file.size,
43599
+ mimeType,
43600
+ metadata,
43601
+ };
43602
+ }
43603
+ //#endregion
43604
+
42888
43605
  //#endregion
42889
43606
  //#region ---- Service ----
42890
43607
  /**
@@ -52036,6 +52753,7 @@ function generateActivityDefinitions() {
52036
52753
  category: CATEGORY['ui'],
52037
52754
  executionMode: 'frontend',
52038
52755
  taskType: 'human-task',
52756
+ workflowContinuation: { beforeInteractive: 'skip-when-chained-from-human-task' },
52039
52757
  icon: 'fa-light fa-clipboard-check',
52040
52758
  outcomes: ['Submitted', 'Saved', 'Cancelled'],
52041
52759
  inputs: [
@@ -52070,6 +52788,135 @@ function generateActivityDefinitions() {
52070
52788
  ],
52071
52789
  outputs: [],
52072
52790
  });
52791
+ definitions.push({
52792
+ name: 'AssessmentManagement.AssessmentSession:ReviewAnswers',
52793
+ type: 'AssessmentManagement.AssessmentSession:ReviewAnswers',
52794
+ title: M$p('Review assessment session answers', 'بازبینی پاسخ‌های جلسه ارزیابی'),
52795
+ description: M$p('Opens readonly answers viewer with Sign off / Reject for manager review. Outcomes: SignedOff, Rejected, Cancelled.', 'نمایش پاسخ‌ها به‌صورت فقط‌خواندنی با دکمه‌های تأیید / رد برای بازبینی مدیر. خروجی‌ها: SignedOff، Rejected، Cancelled'),
52796
+ category: CATEGORY['ui'],
52797
+ executionMode: 'frontend',
52798
+ taskType: 'human-task',
52799
+ workflowContinuation: { beforeInteractive: 'skip-when-chained-from-human-task' },
52800
+ icon: 'fa-light fa-magnifying-glass',
52801
+ outcomes: ['SignedOff', 'Rejected', 'Cancelled'],
52802
+ inputs: [
52803
+ {
52804
+ name: 'caseId',
52805
+ title: 'Case ID',
52806
+ description: 'AssessmentManagement.AssessmentCase id',
52807
+ dataType: 'string',
52808
+ interface: { type: AXPWidgetsList.Editors.TextBox, options: {} },
52809
+ },
52810
+ {
52811
+ name: 'sessionId',
52812
+ title: 'Session ID',
52813
+ description: 'Optional AssessmentManagement.AssessmentSession id',
52814
+ dataType: 'string',
52815
+ interface: { type: AXPWidgetsList.Editors.TextBox, options: {} },
52816
+ },
52817
+ {
52818
+ name: 'title',
52819
+ title: 'Viewer title',
52820
+ description: 'Optional popup title; defaults to assessment case title when omitted',
52821
+ dataType: 'string',
52822
+ interface: { type: AXPWidgetsList.Editors.TextBox, options: {} },
52823
+ },
52824
+ {
52825
+ name: 'showAs',
52826
+ title: 'Show as',
52827
+ description: 'popup',
52828
+ dataType: 'string',
52829
+ interface: { type: AXPWidgetsList.Editors.TextBox, options: {} },
52830
+ },
52831
+ ],
52832
+ outputs: [
52833
+ {
52834
+ name: 'caseId',
52835
+ title: 'Case ID',
52836
+ description: 'Reviewed assessment case id',
52837
+ dataType: 'string',
52838
+ interface: { type: AXPWidgetsList.Editors.TextBox, options: {} },
52839
+ },
52840
+ {
52841
+ name: 'sessionId',
52842
+ title: 'Session ID',
52843
+ description: 'Reviewed assessment session id',
52844
+ dataType: 'string',
52845
+ interface: { type: AXPWidgetsList.Editors.TextBox, options: {} },
52846
+ },
52847
+ {
52848
+ name: 'answers',
52849
+ title: 'Answers',
52850
+ description: 'Session answers snapshot at review time',
52851
+ dataType: 'object',
52852
+ interface: { type: AXPWidgetsList.Advanced.CodeEditor, options: {} },
52853
+ },
52854
+ ],
52855
+ });
52856
+ definitions.push({
52857
+ name: 'AssessmentManagement.AssessmentCase:ReviewAnswers',
52858
+ type: 'AssessmentManagement.AssessmentCase:ReviewAnswers',
52859
+ title: M$p('Review assessment case answers', 'بازبینی پاسخ‌های پرونده ارزیابی'),
52860
+ description: M$p('Opens readonly answers viewer with Sign off / Reject for manager review. Outcomes: SignedOff, Rejected, Cancelled.', 'نمایش پاسخ‌ها به‌صورت فقط‌خواندنی با دکمه‌های تأیید / رد برای بازبینی مدیر. خروجی‌ها: SignedOff، Rejected، Cancelled'),
52861
+ category: CATEGORY['ui'],
52862
+ executionMode: 'frontend',
52863
+ taskType: 'ui-activity',
52864
+ icon: 'fa-light fa-magnifying-glass',
52865
+ outcomes: ['SignedOff', 'Rejected', 'Cancelled'],
52866
+ inputs: [
52867
+ {
52868
+ name: 'caseId',
52869
+ title: 'Case ID',
52870
+ description: 'AssessmentManagement.AssessmentCase id',
52871
+ dataType: 'string',
52872
+ interface: { type: AXPWidgetsList.Editors.TextBox, options: {} },
52873
+ },
52874
+ {
52875
+ name: 'sessionId',
52876
+ title: 'Session ID',
52877
+ description: 'Optional AssessmentManagement.AssessmentSession id',
52878
+ dataType: 'string',
52879
+ interface: { type: AXPWidgetsList.Editors.TextBox, options: {} },
52880
+ },
52881
+ {
52882
+ name: 'title',
52883
+ title: 'Viewer title',
52884
+ description: 'Optional popup title; defaults to assessment case title when omitted',
52885
+ dataType: 'string',
52886
+ interface: { type: AXPWidgetsList.Editors.TextBox, options: {} },
52887
+ },
52888
+ {
52889
+ name: 'showAs',
52890
+ title: 'Show as',
52891
+ description: 'popup',
52892
+ dataType: 'string',
52893
+ interface: { type: AXPWidgetsList.Editors.TextBox, options: {} },
52894
+ },
52895
+ ],
52896
+ outputs: [
52897
+ {
52898
+ name: 'caseId',
52899
+ title: 'Case ID',
52900
+ description: 'Reviewed assessment case id',
52901
+ dataType: 'string',
52902
+ interface: { type: AXPWidgetsList.Editors.TextBox, options: {} },
52903
+ },
52904
+ {
52905
+ name: 'sessionId',
52906
+ title: 'Session ID',
52907
+ description: 'Reviewed assessment session id',
52908
+ dataType: 'string',
52909
+ interface: { type: AXPWidgetsList.Editors.TextBox, options: {} },
52910
+ },
52911
+ {
52912
+ name: 'answers',
52913
+ title: 'Answers',
52914
+ description: 'Session answers snapshot at review time',
52915
+ dataType: 'object',
52916
+ interface: { type: AXPWidgetsList.Advanced.CodeEditor, options: {} },
52917
+ },
52918
+ ],
52919
+ });
52073
52920
  // If (branch) Activity (backend – evaluates condition, outcomes Then / Else)
52074
52921
  definitions.push({
52075
52922
  name: 'workflow-activity:if',
@@ -52841,60 +53688,36 @@ function generateActivityDefinitions() {
52841
53688
  },
52842
53689
  ],
52843
53690
  });
52844
- // Collect Signature Activity
53691
+ // Sign-off Activity
52845
53692
  definitions.push({
52846
- name: 'workflow-activity:collect-signature',
52847
- type: 'workflow-activity:collect-signature',
52848
- title: M$p('Collect Signature', 'جمع‌آوری امضا'),
52849
- instanceTitle: '{{inputs.message || inputs.refType}} · {{inputs.refId}}',
52850
- description: M$p('Collects a signature from a user through a dialog', 'جمع‌آوری امضا از کاربر از طریق گفتگو'),
53693
+ name: 'workflow-activity:sign-off',
53694
+ type: 'workflow-activity:sign-off',
53695
+ title: M$p('Sign off', 'تأیید و امضا'),
53696
+ description: M$p('Collects a required digital signature and optional note to complete approval sign-off', 'جمع‌آوری امضای دیجیتال الزامی و یادداشت اختیاری برای تکمیل تأیید'),
52851
53697
  category: CATEGORY['human-tasks'],
52852
53698
  executionMode: 'frontend',
52853
53699
  taskType: 'human-task',
52854
- icon: 'fa-pen',
53700
+ workflowContinuation: { beforeInteractive: 'skip-for-assignee' },
53701
+ icon: 'fa-pen-fancy',
52855
53702
  outcomes: ['Signed', 'Cancelled'],
52856
53703
  inputs: [
52857
53704
  {
52858
- name: 'signatureRequestId',
52859
- title: 'Signature Request ID',
52860
- description: 'ID of the signature request',
52861
- dataType: 'string',
52862
- interface: {
52863
- type: AXPWidgetsList.Editors.TextBox,
52864
- options: {
52865
- placeholder: 'Enter signature request ID',
52866
- },
52867
- },
52868
- validations: [
52869
- {
52870
- rule: 'required',
52871
- },
52872
- ],
52873
- },
52874
- {
52875
- name: 'signerId',
52876
- title: 'Signer ID',
52877
- description: 'ID of the user who needs to sign',
53705
+ name: 'message',
53706
+ title: 'Message',
53707
+ description: 'Optional message shown in the sign-off dialog',
52878
53708
  dataType: 'string',
52879
53709
  interface: {
52880
- type: AXPWidgetsList.Editors.LookupBox,
53710
+ type: AXPWidgetsList.Editors.LargeTextBox,
52881
53711
  options: {
52882
- entity: 'SecurityManagement.User',
52883
- multiple: false,
52884
- valueField: 'id',
52885
- textField: 'title',
53712
+ placeholder: 'Enter message for approver',
53713
+ rows: 3,
52886
53714
  },
52887
53715
  },
52888
- validations: [
52889
- {
52890
- rule: 'required',
52891
- },
52892
- ],
52893
53716
  },
52894
53717
  {
52895
53718
  name: 'refId',
52896
53719
  title: 'Reference ID',
52897
- description: 'ID of the entity record',
53720
+ description: 'Optional entity record id for workflow context',
52898
53721
  dataType: 'string',
52899
53722
  interface: {
52900
53723
  type: AXPWidgetsList.Editors.TextBox,
@@ -52902,16 +53725,11 @@ function generateActivityDefinitions() {
52902
53725
  placeholder: 'Enter entity record ID',
52903
53726
  },
52904
53727
  },
52905
- validations: [
52906
- {
52907
- rule: 'required',
52908
- },
52909
- ],
52910
53728
  },
52911
53729
  {
52912
53730
  name: 'refType',
52913
53731
  title: 'Reference Type',
52914
- description: 'Entity type in module.entity format',
53732
+ description: 'Optional entity type in module.entity format',
52915
53733
  dataType: 'string',
52916
53734
  interface: {
52917
53735
  type: AXPWidgetsList.Editors.TextBox,
@@ -52919,24 +53737,6 @@ function generateActivityDefinitions() {
52919
53737
  placeholder: 'Enter entity type',
52920
53738
  },
52921
53739
  },
52922
- validations: [
52923
- {
52924
- rule: 'required',
52925
- },
52926
- ],
52927
- },
52928
- {
52929
- name: 'message',
52930
- title: 'Message',
52931
- description: 'Message to display to the signer',
52932
- dataType: 'string',
52933
- interface: {
52934
- type: AXPWidgetsList.Editors.LargeTextBox,
52935
- options: {
52936
- placeholder: 'Enter message for signer',
52937
- rows: 3,
52938
- },
52939
- },
52940
53740
  },
52941
53741
  ],
52942
53742
  outputs: [
@@ -52950,14 +53750,74 @@ function generateActivityDefinitions() {
52950
53750
  {
52951
53751
  name: 'note',
52952
53752
  title: 'Note',
52953
- description: 'Optional note from the signer',
53753
+ description: 'Optional note from the approver',
52954
53754
  dataType: 'string',
52955
53755
  interface: { type: AXPWidgetsList.Editors.TextBox, options: {} },
52956
53756
  },
52957
53757
  {
52958
53758
  name: 'signedAt',
52959
53759
  title: 'Signed At',
52960
- description: 'Timestamp when signature was collected',
53760
+ description: 'Timestamp when sign-off was captured',
53761
+ dataType: 'string',
53762
+ interface: { type: AXPWidgetsList.Editors.TextBox, options: {} },
53763
+ },
53764
+ ],
53765
+ });
53766
+ // Rejection Reason Activity
53767
+ definitions.push({
53768
+ name: 'workflow-activity:rejection-reason',
53769
+ type: 'workflow-activity:rejection-reason',
53770
+ title: M$p('Rejection reason', 'دلیل رد'),
53771
+ description: M$p('Shows a dialog to capture rejection reason and optional note', 'نمایش گفتگو برای ثبت دلیل رد و یادداشت اختیاری'),
53772
+ category: CATEGORY['human-tasks'],
53773
+ executionMode: 'frontend',
53774
+ taskType: 'human-task',
53775
+ icon: 'fa-ban',
53776
+ outcomes: ['Submitted', 'Cancelled'],
53777
+ inputs: [
53778
+ {
53779
+ name: 'message',
53780
+ title: 'Message',
53781
+ description: 'Optional message shown in the rejection dialog',
53782
+ dataType: 'string',
53783
+ interface: {
53784
+ type: AXPWidgetsList.Editors.LargeTextBox,
53785
+ options: {
53786
+ placeholder: 'Enter message for reviewer',
53787
+ rows: 3,
53788
+ },
53789
+ },
53790
+ },
53791
+ {
53792
+ name: 'requireReason',
53793
+ title: 'Require reason',
53794
+ description: 'When enabled, reason must be provided before submit',
53795
+ dataType: 'boolean',
53796
+ interface: {
53797
+ type: AXPWidgetsList.Editors.ToggleSwitch,
53798
+ options: {},
53799
+ },
53800
+ },
53801
+ ],
53802
+ outputs: [
53803
+ {
53804
+ name: 'reason',
53805
+ title: 'Reason',
53806
+ description: 'Rejection reason',
53807
+ dataType: 'string',
53808
+ interface: { type: AXPWidgetsList.Editors.LargeTextBox, options: {} },
53809
+ },
53810
+ {
53811
+ name: 'note',
53812
+ title: 'Note',
53813
+ description: 'Optional additional note',
53814
+ dataType: 'string',
53815
+ interface: { type: AXPWidgetsList.Editors.TextBox, options: {} },
53816
+ },
53817
+ {
53818
+ name: 'rejectedAt',
53819
+ title: 'Rejected At',
53820
+ description: 'Timestamp when rejection was captured',
52961
53821
  dataType: 'string',
52962
53822
  interface: { type: AXPWidgetsList.Editors.TextBox, options: {} },
52963
53823
  },
@@ -53916,8 +54776,7 @@ const employeeLifecycleEventFlowWorkflowDefinition = {
53916
54776
  employeeId: '{{ inputs.employeeId }}',
53917
54777
  eventTypeId: '{{ inputs.eventTypeId }}',
53918
54778
  assignedToUserId: '{{ variables.managerUserId || variables.initiatorUserId }}',
53919
- effectiveDate: '{{ inputs.effectiveDate }}',
53920
- notes: '',
54779
+ statusId: 'in-progress',
53921
54780
  },
53922
54781
  },
53923
54782
  },
@@ -53927,14 +54786,7 @@ const employeeLifecycleEventFlowWorkflowDefinition = {
53927
54786
  title: 'Create lifecycle event',
53928
54787
  inputs: {
53929
54788
  entity: 'HumanCapitalManagement.LifecycleEvent',
53930
- data: {
53931
- employeeId: '{{ inputs.employeeId }}',
53932
- eventTypeId: '{{ inputs.eventTypeId }}',
53933
- assignedToUserId: '{{ variables.assignedToUserId }}',
53934
- effectiveDate: '{{ variables.effectiveDate || inputs.effectiveDate }}',
53935
- notes: '{{ variables.notes }}',
53936
- statusId: 'in-progress',
53937
- },
54789
+ data: '{{ outputs.result }}',
53938
54790
  },
53939
54791
  outputToVariables: {
53940
54792
  lifecycleEventId: 'id',
@@ -54086,23 +54938,43 @@ const employeeLifecycleEventFlowWorkflowDefinition = {
54086
54938
  actions: {
54087
54939
  suffix: [
54088
54940
  {
54089
- name: 'approve',
54090
- title: 'Approve',
54091
- icon: 'fa-light fa-check',
54092
- color: 'success',
54093
- command: { name: 'approve' },
54094
- },
54095
- {
54096
- name: 'reject',
54097
- title: 'Reject',
54098
- icon: 'fa-light fa-times',
54099
- color: 'danger',
54100
- command: { name: 'reject' },
54941
+ name: 'review',
54942
+ title: 'Review',
54943
+ icon: 'fa-light fa-magnifying-glass',
54944
+ color: 'primary',
54945
+ command: { name: 'review' },
54101
54946
  },
54102
54947
  ],
54103
54948
  },
54104
54949
  },
54105
54950
  },
54951
+ {
54952
+ id: 'reviewLifecycleQuestionnaire',
54953
+ name: 'AssessmentManagement.AssessmentCase:ReviewAnswers',
54954
+ inputs: {
54955
+ caseId: '{{ variables.assessmentCaseId }}',
54956
+ sessionId: '{{ variables.assessmentSessionId }}',
54957
+ title: '{{ inputs.assessmentCaseTitle || inputs.employeeDisplayName }}',
54958
+ showAs: 'popup',
54959
+ },
54960
+ },
54961
+ {
54962
+ id: 'managerSignOffLifecycle',
54963
+ name: 'workflow-activity:sign-off',
54964
+ inputs: {
54965
+ message: '@human-capital-management:lifecycle-events.messages.sign-off',
54966
+ refId: '{{ variables.lifecycleEventId }}',
54967
+ refType: 'HumanCapitalManagement.LifecycleEvent',
54968
+ },
54969
+ },
54970
+ {
54971
+ id: 'captureLifecycleRejectionReason',
54972
+ name: 'workflow-activity:rejection-reason',
54973
+ inputs: {
54974
+ message: '@human-capital-management:lifecycle-events.messages.rejection',
54975
+ requireReason: true,
54976
+ },
54977
+ },
54106
54978
  {
54107
54979
  id: 'updateEmployeeTargetStatus',
54108
54980
  name: 'workflow-activity:entity-update',
@@ -54236,13 +55108,37 @@ const employeeLifecycleEventFlowWorkflowDefinition = {
54236
55108
  target: { activtyName: 'managerApproveEmployeeStatusTask' },
54237
55109
  },
54238
55110
  {
54239
- source: { activtyName: 'managerApproveEmployeeStatusTask', port: 'approve' },
55111
+ source: { activtyName: 'managerApproveEmployeeStatusTask', port: 'review' },
55112
+ target: { activtyName: 'reviewLifecycleQuestionnaire' },
55113
+ },
55114
+ {
55115
+ source: { activtyName: 'reviewLifecycleQuestionnaire', port: 'SignedOff' },
55116
+ target: { activtyName: 'managerSignOffLifecycle' },
55117
+ },
55118
+ {
55119
+ source: { activtyName: 'reviewLifecycleQuestionnaire', port: 'Rejected' },
55120
+ target: { activtyName: 'captureLifecycleRejectionReason' },
55121
+ },
55122
+ {
55123
+ source: { activtyName: 'reviewLifecycleQuestionnaire', port: 'Cancelled' },
55124
+ target: { activtyName: 'managerApproveEmployeeStatusTask' },
55125
+ },
55126
+ {
55127
+ source: { activtyName: 'managerSignOffLifecycle', port: 'Signed' },
54240
55128
  target: { activtyName: 'updateEmployeeTargetStatus' },
54241
55129
  },
54242
55130
  {
54243
- source: { activtyName: 'managerApproveEmployeeStatusTask', port: 'reject' },
55131
+ source: { activtyName: 'managerSignOffLifecycle', port: 'Cancelled' },
55132
+ target: { activtyName: 'managerApproveEmployeeStatusTask' },
55133
+ },
55134
+ {
55135
+ source: { activtyName: 'captureLifecycleRejectionReason', port: 'Submitted' },
54244
55136
  target: { activtyName: 'updateLifecycleEventCancelled' },
54245
55137
  },
55138
+ {
55139
+ source: { activtyName: 'captureLifecycleRejectionReason', port: 'Cancelled' },
55140
+ target: { activtyName: 'managerApproveEmployeeStatusTask' },
55141
+ },
54246
55142
  {
54247
55143
  source: { activtyName: 'updateLifecycleEventCancelled', port: 'Done' },
54248
55144
  target: { activtyName: 'cancelAssessmentCaseOnReject' },
@@ -61598,91 +62494,6 @@ const historyMiddleware = {
61598
62494
  },
61599
62495
  };
61600
62496
 
61601
- /**
61602
- * Signature Loader Middleware
61603
- *
61604
- * This middleware loads digital signatures for entities by attempting to query
61605
- * the corresponding signature table ({EntityName}Signature).
61606
- *
61607
- * Behavior:
61608
- * - Only runs on 'getOne' operation (entity details)
61609
- * - Attempts to query signature table without checking plugin existence
61610
- * - If signature table exists and has data, attaches signatures to result
61611
- * - If table doesn't exist or query fails, silently continues
61612
- *
61613
- * Example:
61614
- * Entity: "ContentManagement.Promotion"
61615
- * Signature table: "ContentManagement.PromotionSignature"
61616
- * Result: ctx.result.signatures = [{ id, signed, meta, ... }]
61617
- */
61618
- const signatureLoaderMiddleware = {
61619
- //#region ---- Middleware Configuration ----
61620
- target: {
61621
- ops: ['getOne'], // Only for getOne operations (details view)
61622
- order: 85, // After main operation, before event dispatch
61623
- },
61624
- //#endregion
61625
- //#region ---- Middleware Execution ----
61626
- execute: async (ctx, next) => {
61627
- // Execute the main operation first to get the entity data
61628
- await next();
61629
- // Skip if no result or no record ID
61630
- if (!ctx.result || !ctx.result.id) {
61631
- return;
61632
- }
61633
- try {
61634
- // Parse entity name (format: "Module.EntityName")
61635
- const [moduleName, entityName] = ctx.entityName.split('.');
61636
- // Skip if entity name format is invalid
61637
- if (!moduleName || !entityName) {
61638
- return;
61639
- }
61640
- // Build signature entity name: {Module}.{EntityName}Signature
61641
- const signatureEntityName = `${moduleName}.${entityName}Signature`;
61642
- const recordId = ctx.result.id;
61643
- try {
61644
- // Attempt to query signatures table
61645
- // If table doesn't exist, this will throw an error and we'll catch it
61646
- const signaturesResult = await ctx.backend.query(signatureEntityName, {
61647
- skip: 0,
61648
- take: 1000, // Get all signatures
61649
- filter: {
61650
- field: ctx.entityName, // Field name is the full entity name
61651
- operator: { type: 'equal' },
61652
- value: recordId,
61653
- },
61654
- });
61655
- // Attach signatures to result if found
61656
- if (signaturesResult?.items && signaturesResult.items.length > 0) {
61657
- ctx.result.signatures = signaturesResult.items;
61658
- // Log for debugging
61659
- console.log(`[signature-loader] ✅ Loaded ${signaturesResult.items.length} signature(s) for ${ctx.entityName}#${recordId}`);
61660
- }
61661
- else {
61662
- // No signatures found, set empty array
61663
- ctx.result.signatures = [];
61664
- }
61665
- }
61666
- catch (error) {
61667
- // Signature table doesn't exist or query failed
61668
- // This is expected for entities without sign plugin, so we silently continue
61669
- console.debug(`[signature-loader] ℹ️ No signature table found for ${ctx.entityName} (this is normal for entities without sign plugin)`);
61670
- // Set empty signatures array
61671
- ctx.result.signatures = [];
61672
- }
61673
- }
61674
- catch (error) {
61675
- // Unexpected error in middleware, log but don't fail the operation
61676
- console.error('[signature-loader] ❌ Unexpected error in signature loader middleware:', error);
61677
- // Set empty signatures array on error
61678
- if (ctx.result) {
61679
- ctx.result.signatures = [];
61680
- }
61681
- }
61682
- },
61683
- //#endregion
61684
- };
61685
-
61686
62497
  //#region ---- Lock Guard Middleware ----
61687
62498
  /**
61688
62499
  * Middleware that prevents editing or deleting locked records.
@@ -62509,7 +63320,6 @@ class AXCMiddlewaresModule {
62509
63320
  { provide: AXP_ENTITY_STORAGE_MIDDLEWARE, multi: true, useValue: primaryMiddleware },
62510
63321
  { provide: AXP_ENTITY_STORAGE_MIDDLEWARE, multi: true, useValue: visibilityFilterMiddleware }, // order: 20
62511
63322
  // { provide: AXP_ENTITY_STORAGE_MIDDLEWARE, multi: true, useValue: firestoreRequestLoggerMiddleware }, // order: 200 - runs last before backend, logs request/response
62512
- //{ provide: AXP_ENTITY_STORAGE_MIDDLEWARE, multi: true, useValue: signatureLoaderMiddleware },
62513
63323
  // Sample entity event listener to show logs for all entity.* events
62514
63324
  //{ provide: AXP_DISTRIBUTED_EVENT_LISTENER_PROVIDER, multi: true, useValue: AXCMockEntityLogListener },
62515
63325
  ], imports: [AXCEntityStorageModule, AXCEntityDefinitionsModule] }); }
@@ -62536,7 +63346,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
62536
63346
  { provide: AXP_ENTITY_STORAGE_MIDDLEWARE, multi: true, useValue: primaryMiddleware },
62537
63347
  { provide: AXP_ENTITY_STORAGE_MIDDLEWARE, multi: true, useValue: visibilityFilterMiddleware }, // order: 20
62538
63348
  // { provide: AXP_ENTITY_STORAGE_MIDDLEWARE, multi: true, useValue: firestoreRequestLoggerMiddleware }, // order: 200 - runs last before backend, logs request/response
62539
- //{ provide: AXP_ENTITY_STORAGE_MIDDLEWARE, multi: true, useValue: signatureLoaderMiddleware },
62540
63349
  // Sample entity event listener to show logs for all entity.* events
62541
63350
  //{ provide: AXP_DISTRIBUTED_EVENT_LISTENER_PROVIDER, multi: true, useValue: AXCMockEntityLogListener },
62542
63351
  ],
@@ -70614,7 +71423,7 @@ class AXCSecurityManagementMockModule {
70614
71423
  provideQuerySetups([
70615
71424
  {
70616
71425
  key: 'SecurityManagement:User:RolesForListColumn',
70617
- loader: () => import('./acorex-connectivity-mock-user-roles-for-list-column.query-nadNnJKc.mjs').then((m) => m.UserRolesForListColumnQuery),
71426
+ loader: () => import('./acorex-connectivity-mock-user-roles-for-list-column.query-BLkdnyel.mjs').then((m) => m.UserRolesForListColumnQuery),
70618
71427
  },
70619
71428
  ]),
70620
71429
  ] }); }
@@ -70658,7 +71467,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
70658
71467
  provideQuerySetups([
70659
71468
  {
70660
71469
  key: 'SecurityManagement:User:RolesForListColumn',
70661
- loader: () => import('./acorex-connectivity-mock-user-roles-for-list-column.query-nadNnJKc.mjs').then((m) => m.UserRolesForListColumnQuery),
71470
+ loader: () => import('./acorex-connectivity-mock-user-roles-for-list-column.query-BLkdnyel.mjs').then((m) => m.UserRolesForListColumnQuery),
70662
71471
  },
70663
71472
  ]),
70664
71473
  ],
@@ -75664,7 +76473,7 @@ class AXCWorkflowEngine {
75664
76473
  bookmarkPayload['actions'] = inputs['actions'] || null;
75665
76474
  bookmarkPayload['context'] = inputs['context'] || {};
75666
76475
  }
75667
- if (activityType === 'workflow-activity:cartable') {
76476
+ if (activityType === RootConfig$l.activities.cartable) {
75668
76477
  bookmarkPayload['assignedUserIds'] = [];
75669
76478
  }
75670
76479
  if (resolvedTaskTypeForBookmark === 'human-task') {
@@ -76012,8 +76821,8 @@ class AXCWorkflowEngine {
76012
76821
  const payloadActivityType = String(resumePayload['activityType'] ?? '');
76013
76822
  const assigned = this.normalizeUserIds(resumePayload['assignedUserIds']) ?? [];
76014
76823
  const candidates = this.normalizeUserIds(resumePayload['candidateUserIds']) ?? [];
76015
- const isCartablePayload = payloadActivityType === 'workflow-activity:cartable';
76016
- const isPooledHumanPayload = payloadActivityType === 'workflow-activity:human-task' &&
76824
+ const isCartablePayload = payloadActivityType === RootConfig$l.activities.cartable;
76825
+ const isPooledHumanPayload = payloadActivityType === RootConfig$l.activities.humanTask &&
76017
76826
  assigned.length === 0 &&
76018
76827
  candidates.length > 0;
76019
76828
  if (isCartablePayload || isPooledHumanPayload) {
@@ -76161,7 +76970,7 @@ class AXCWorkflowEngine {
76161
76970
  bookmarkPayload['actions'] = inputs['actions'] || null;
76162
76971
  bookmarkPayload['context'] = inputs['context'] || {};
76163
76972
  }
76164
- if (activityType === 'workflow-activity:cartable') {
76973
+ if (activityType === RootConfig$l.activities.cartable) {
76165
76974
  bookmarkPayload['assignedUserIds'] = [];
76166
76975
  }
76167
76976
  if (resolvedTaskType === 'human-task') {
@@ -76306,6 +77115,56 @@ class AXCWorkflowEngine {
76306
77115
  // Convert instance to state (async - needs bookmark lookup)
76307
77116
  return await this.instanceToInstanceState(instance);
76308
77117
  }
77118
+ /**
77119
+ * Restores a suspended task-board step when the user declines a pre-interactive continuation prompt.
77120
+ * Re-opens the human-task bookmark on the task board and removes the aborted inline step bookmark.
77121
+ */
77122
+ async revertResumeAfterDeclinedInteractiveContinuation(request) {
77123
+ try {
77124
+ const instance = await this.getInstance(request.instanceId);
77125
+ if (!instance) {
77126
+ return { success: false, error: `Workflow instance not found: ${request.instanceId}` };
77127
+ }
77128
+ if (request.abortedStepId) {
77129
+ const abortedBookmarks = await this.store.getBookmarksByInstanceAndActivity(request.instanceId, request.abortedStepId, false);
77130
+ for (const bookmark of abortedBookmarks) {
77131
+ if (!bookmark.isConsumed) {
77132
+ bookmark.isConsumed = true;
77133
+ await this.store.updateBookmark(bookmark);
77134
+ }
77135
+ }
77136
+ }
77137
+ const suspendedBookmarks = await this.store.getBookmarksByInstanceAndActivity(request.instanceId, request.suspendedStepId, false);
77138
+ let restoredBookmark = (request.bookmarkId
77139
+ ? suspendedBookmarks.find((bookmark) => bookmark.id === request.bookmarkId)
77140
+ : null) ?? suspendedBookmarks[0];
77141
+ if (!restoredBookmark) {
77142
+ return { success: false, error: 'Suspended step bookmark not found' };
77143
+ }
77144
+ const payload = this.parseBookmarkPayloadJson(restoredBookmark.payloadJson) ?? {};
77145
+ const taskToken = this.generateTaskToken(request.instanceId, request.suspendedStepId);
77146
+ payload['taskToken'] = taskToken;
77147
+ restoredBookmark.payloadJson = JSON.stringify(payload);
77148
+ restoredBookmark.isConsumed = false;
77149
+ await this.store.updateBookmark(restoredBookmark);
77150
+ const state = await this.getState({ instanceId: request.instanceId });
77151
+ const revertedState = {
77152
+ ...state,
77153
+ status: 'suspended',
77154
+ currentStepId: request.suspendedStepId,
77155
+ lastUpdated: new Date(),
77156
+ };
77157
+ await this.updateInstanceFromState(request.instanceId, revertedState);
77158
+ return {
77159
+ success: true,
77160
+ state: revertedState,
77161
+ };
77162
+ }
77163
+ catch (error) {
77164
+ const message = error instanceof Error ? error.message : 'Failed to revert workflow resume';
77165
+ return { success: false, error: message };
77166
+ }
77167
+ }
76309
77168
  /**
76310
77169
  * Claim a pooled task (cartable or human-task with candidates only): assign current user without resuming.
76311
77170
  */
@@ -76341,8 +77200,8 @@ class AXCWorkflowEngine {
76341
77200
  if (assigned.length > 0) {
76342
77201
  return { success: false, error: 'This task is already claimed' };
76343
77202
  }
76344
- const isCartable = activityType === 'workflow-activity:cartable';
76345
- const isPooledHuman = activityType === 'workflow-activity:human-task' && candidates.length > 0;
77203
+ const isCartable = activityType === RootConfig$l.activities.cartable;
77204
+ const isPooledHuman = activityType === RootConfig$l.activities.humanTask && candidates.length > 0;
76346
77205
  if (!isCartable && !isPooledHuman) {
76347
77206
  return { success: false, error: 'This task cannot be claimed' };
76348
77207
  }
@@ -76407,8 +77266,8 @@ class AXCWorkflowEngine {
76407
77266
  if (assigned.length > 0) {
76408
77267
  return { success: false, error: 'This task is already claimed' };
76409
77268
  }
76410
- const isCartable = activityType === 'workflow-activity:cartable';
76411
- const isPooledHuman = activityType === 'workflow-activity:human-task' && candidates.length > 0;
77269
+ const isCartable = activityType === RootConfig$l.activities.cartable;
77270
+ const isPooledHuman = activityType === RootConfig$l.activities.humanTask && candidates.length > 0;
76412
77271
  if (!isCartable && !isPooledHuman) {
76413
77272
  return { success: false, error: 'This task cannot be claimed' };
76414
77273
  }
@@ -76603,7 +77462,7 @@ class AXCWorkflowEngine {
76603
77462
  }
76604
77463
  validateHumanTaskReassignPayload(payload, uid) {
76605
77464
  const activityType = String(payload['activityType'] ?? '');
76606
- if (activityType !== 'workflow-activity:human-task') {
77465
+ if (activityType !== RootConfig$l.activities.humanTask) {
76607
77466
  return { ok: false, error: 'Only human tasks can be reassigned to yourself' };
76608
77467
  }
76609
77468
  const assigned = this.normalizeUserIds(payload['assignedUserIds']) ?? [];
@@ -76637,7 +77496,7 @@ class AXCWorkflowEngine {
76637
77496
  * Activities that suspend for the task board (inbox), same completion path as human-task.
76638
77497
  */
76639
77498
  isTaskBoardSuspendGraphActivity(activityType) {
76640
- return activityType === 'workflow-activity:human-task' || activityType === 'workflow-activity:cartable';
77499
+ return activityType === RootConfig$l.activities.humanTask || activityType === RootConfig$l.activities.cartable;
76641
77500
  }
76642
77501
  /**
76643
77502
  * Determine execution mode for an activity (async).
@@ -76654,7 +77513,7 @@ class AXCWorkflowEngine {
76654
77513
  async determineExecutionMode(activityType, activity) {
76655
77514
  // 1. Check if executionMode is explicitly set in activity instance (highest priority)
76656
77515
  if (activity?.metadata && activity.metadata['executionMode']) {
76657
- if (activityType === 'workflow-activity:human-task') {
77516
+ if (activityType === RootConfig$l.activities.humanTask) {
76658
77517
  console.log(`[AXCWorkflowEngine] determineExecutionMode(${activityType}): from instance metadata →`, activity.metadata['executionMode']);
76659
77518
  }
76660
77519
  return activity.metadata['executionMode'];
@@ -76662,7 +77521,7 @@ class AXCWorkflowEngine {
76662
77521
  // 2. Check cache
76663
77522
  const cached = this.activityDefinitionCache.get(activityType);
76664
77523
  if (cached && Date.now() - cached.cachedAt.getTime() < this.CACHE_TTL_MS) {
76665
- if (activityType === 'workflow-activity:human-task') {
77524
+ if (activityType === RootConfig$l.activities.humanTask) {
76666
77525
  console.log(`[AXCWorkflowEngine] determineExecutionMode(${activityType}): from cache →`, cached.executionMode);
76667
77526
  }
76668
77527
  return cached.executionMode;
@@ -76670,7 +77529,7 @@ class AXCWorkflowEngine {
76670
77529
  // 3. Query ActivityDefinitionService
76671
77530
  try {
76672
77531
  const activityDef = await this.activityDefinitionService.getActivityByName(activityType);
76673
- if (activityType === 'workflow-activity:human-task') {
77532
+ if (activityType === RootConfig$l.activities.humanTask) {
76674
77533
  console.log(`[AXCWorkflowEngine] determineExecutionMode(${activityType}): from definition →`, {
76675
77534
  definitionFound: !!activityDef,
76676
77535
  executionMode: activityDef?.executionMode,
@@ -76690,7 +77549,7 @@ class AXCWorkflowEngine {
76690
77549
  }
76691
77550
  // 4. Default to frontend
76692
77551
  const defaultMode = 'frontend';
76693
- if (activityType === 'workflow-activity:human-task') {
77552
+ if (activityType === RootConfig$l.activities.humanTask) {
76694
77553
  console.log(`[AXCWorkflowEngine] determineExecutionMode(${activityType}): using default →`, defaultMode);
76695
77554
  }
76696
77555
  this.activityDefinitionCache.set(activityType, {
@@ -76725,6 +77584,7 @@ class AXCWorkflowEngine {
76725
77584
  taskType: taskType,
76726
77585
  input: executionMode === 'frontend' || executionMode === 'both' ? properties : undefined,
76727
77586
  config: executionMode === 'frontend' || executionMode === 'both' ? properties : undefined,
77587
+ continuation: activityDef?.workflowContinuation,
76728
77588
  };
76729
77589
  }
76730
77590
  /**
@@ -76885,7 +77745,7 @@ class AXCWorkflowEngine {
76885
77745
  return false;
76886
77746
  }
76887
77747
  const t = payload['activityType'];
76888
- return t === 'workflow-activity:human-task' || t === 'workflow-activity:cartable';
77748
+ return t === RootConfig$l.activities.humanTask || t === RootConfig$l.activities.cartable;
76889
77749
  }
76890
77750
  /**
76891
77751
  * Primary user id for assignee column: suspended task-board bookmark (assigned, then candidate users),
@@ -78023,7 +78883,7 @@ class AXCWorkflowEngine {
78023
78883
  bookmarkPayload['actions'] = inputs['actions'] || null;
78024
78884
  bookmarkPayload['context'] = inputs['context'] || {};
78025
78885
  }
78026
- if (activityType === 'workflow-activity:cartable') {
78886
+ if (activityType === RootConfig$l.activities.cartable) {
78027
78887
  bookmarkPayload['assignedUserIds'] = [];
78028
78888
  }
78029
78889
  if (resolvedTaskTypeComplete === 'human-task') {
@@ -78175,8 +79035,8 @@ class AXCWorkflowEngine {
78175
79035
  const bookmarks = await this.getActiveBookmarks(instance.id);
78176
79036
  for (const b of bookmarks) {
78177
79037
  const payload = this.parseBookmarkPayload(b);
78178
- if (payload?.activityType === 'workflow-activity:human-task' ||
78179
- payload?.activityType === 'workflow-activity:cartable') {
79038
+ if (payload?.activityType === RootConfig$l.activities.humanTask ||
79039
+ payload?.activityType === RootConfig$l.activities.cartable) {
78180
79040
  continue;
78181
79041
  }
78182
79042
  const taskToken = payload?.taskToken;
@@ -78204,8 +79064,8 @@ class AXCWorkflowEngine {
78204
79064
  const bookmarks = await this.getActiveBookmarks(instance.id);
78205
79065
  for (const b of bookmarks) {
78206
79066
  const payload = this.parseBookmarkPayload(b);
78207
- if (payload?.activityType === 'workflow-activity:human-task' ||
78208
- payload?.activityType === 'workflow-activity:cartable') {
79067
+ if (payload?.activityType === RootConfig$l.activities.humanTask ||
79068
+ payload?.activityType === RootConfig$l.activities.cartable) {
78209
79069
  continue;
78210
79070
  }
78211
79071
  await this.frontActivtyComplete({
@@ -78268,7 +79128,7 @@ class AXCWorkflowManagementMockModule {
78268
79128
  provideCommandSetups([
78269
79129
  {
78270
79130
  key: 'workflow-activity:assign-to-manager',
78271
- command: () => import('./acorex-connectivity-mock-assign-to-manager.activity-NlqPDd5p.mjs').then((c) => c.AssignToManagerActivity),
79131
+ command: () => import('./acorex-connectivity-mock-assign-to-manager.activity-DR_QQMhA.mjs').then((c) => c.AssignToManagerActivity),
78272
79132
  },
78273
79133
  {
78274
79134
  key: 'workflow-activity:get-current-user-manager',
@@ -78363,7 +79223,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
78363
79223
  provideCommandSetups([
78364
79224
  {
78365
79225
  key: 'workflow-activity:assign-to-manager',
78366
- command: () => import('./acorex-connectivity-mock-assign-to-manager.activity-NlqPDd5p.mjs').then((c) => c.AssignToManagerActivity),
79226
+ command: () => import('./acorex-connectivity-mock-assign-to-manager.activity-DR_QQMhA.mjs').then((c) => c.AssignToManagerActivity),
78367
79227
  },
78368
79228
  {
78369
79229
  key: 'workflow-activity:get-current-user-manager',
@@ -82365,6 +83225,306 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
82365
83225
  }]
82366
83226
  }] });
82367
83227
 
83228
+ //#region ---- Imports ----
83229
+ //#endregion
83230
+ //#region ---- Category codes ----
83231
+ const HAZARD_CATEGORY_CODES = {
83232
+ asbestos: 'ASBESTOS',
83233
+ hazardousSubstance: 'HAZARDOUS_SUBSTANCE',
83234
+ siteHazard: 'SITE_HAZARD',
83235
+ electricalHazard: 'ELECTRICAL_HAZARD',
83236
+ };
83237
+ //#endregion
83238
+ //#region ---- Mock data ----
83239
+ const hazardCategoryMocks = [
83240
+ {
83241
+ id: AXPDataGenerator.uuid(),
83242
+ code: HAZARD_CATEGORY_CODES.asbestos,
83243
+ title: 'Asbestos',
83244
+ description: 'Asbestos-related workplace hazards.',
83245
+ icon: 'fa-light fa-layer-group',
83246
+ color: '#78716c',
83247
+ childrenCount: 0,
83248
+ },
83249
+ {
83250
+ id: AXPDataGenerator.uuid(),
83251
+ code: HAZARD_CATEGORY_CODES.hazardousSubstance,
83252
+ title: 'Hazardous Substance',
83253
+ description: 'Chemical and hazardous substance exposures.',
83254
+ icon: 'fa-light fa-flask',
83255
+ color: '#f59e0b',
83256
+ childrenCount: 0,
83257
+ },
83258
+ {
83259
+ id: AXPDataGenerator.uuid(),
83260
+ code: HAZARD_CATEGORY_CODES.siteHazard,
83261
+ title: 'Site Hazard',
83262
+ description: 'General site and environmental hazards.',
83263
+ icon: 'fa-light fa-hard-hat',
83264
+ color: '#0ea5e9',
83265
+ childrenCount: 0,
83266
+ },
83267
+ {
83268
+ id: AXPDataGenerator.uuid(),
83269
+ code: HAZARD_CATEGORY_CODES.electricalHazard,
83270
+ title: 'Electrical Hazard',
83271
+ description: 'Electrical shock, arc flash, and energised work risks.',
83272
+ icon: 'fa-light fa-bolt',
83273
+ color: '#eab308',
83274
+ childrenCount: 0,
83275
+ },
83276
+ ];
83277
+ //#endregion
83278
+ //#region ---- Resolvers ----
83279
+ function findHazardCategoryByCode(code) {
83280
+ const category = hazardCategoryMocks.find((row) => row.code === code);
83281
+ if (!category) {
83282
+ throw new Error(`Hazard category not found for code: ${code}`);
83283
+ }
83284
+ return category;
83285
+ }
83286
+ function findHazardCategoryByTitle(title) {
83287
+ const category = hazardCategoryMocks.find((row) => resolveMultiLanguageString(row.title, 'en-US') === title || row.title === title);
83288
+ if (!category) {
83289
+ throw new Error(`Hazard category not found for title: ${title}`);
83290
+ }
83291
+ return category;
83292
+ }
83293
+ //#endregion
83294
+
83295
+ //#region ---- Imports ----
83296
+ //#endregion
83297
+ //#region ---- Hazard category seeder ----
83298
+ class AXCHazardCategorySeeder {
83299
+ constructor() {
83300
+ this.storage = inject(AXPEntityStorageService);
83301
+ }
83302
+ async seed() {
83303
+ await this.storage.initial(`${RootConfig$C.module.name}.${RootConfig$C.entities.hazard.name}Category`, hazardCategoryMocks);
83304
+ }
83305
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXCHazardCategorySeeder, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
83306
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXCHazardCategorySeeder }); }
83307
+ }
83308
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXCHazardCategorySeeder, decorators: [{
83309
+ type: Injectable
83310
+ }] });
83311
+
83312
+ //#region ---- Imports ----
83313
+ //#endregion
83314
+ //#region ---- Stable hazard ids ----
83315
+ const MOCK_HAZARD_AMOSITE_ID = 'e5f6a7b8-c9d0-4123-e456-789012345601';
83316
+ const MOCK_HAZARD_TREMOLITE_ID = 'e5f6a7b8-c9d0-4123-e456-789012345602';
83317
+ const MOCK_HAZARD_CHLORINE_HEXIDE_ID = 'e5f6a7b8-c9d0-4123-e456-789012345603';
83318
+ const MOCK_HAZARD_CARBON_DIOXIDE_ID = 'e5f6a7b8-c9d0-4123-e456-789012345604';
83319
+ const MOCK_HAZARD_ELECTROCUTION_ID = 'e5f6a7b8-c9d0-4123-e456-789012345605';
83320
+ //#endregion
83321
+ //#region ---- Helpers ----
83322
+ const withCategories = (categoryCodes) => {
83323
+ const resolved = categoryCodes.map((code) => findHazardCategoryByCode(code));
83324
+ return {
83325
+ categoryIds: resolved.map((category) => category.id),
83326
+ categories: resolved.map((category) => ({
83327
+ id: category.id,
83328
+ title: category.title,
83329
+ })),
83330
+ };
83331
+ };
83332
+ const withTemplate = (questionnaireId) => {
83333
+ const questionnaire = workplaceSafetyQuestionnaires.find((row) => row.id === questionnaireId);
83334
+ if (!questionnaire) {
83335
+ throw new Error(`Questionnaire not found for templateId: ${questionnaireId}`);
83336
+ }
83337
+ return {
83338
+ templateId: questionnaireId,
83339
+ template: {
83340
+ id: questionnaireId,
83341
+ title: resolveMultiLanguageString(questionnaire.title, 'en-US'),
83342
+ },
83343
+ };
83344
+ };
83345
+ //#endregion
83346
+ //#region ---- Mock data ----
83347
+ const hazardMock = [
83348
+ {
83349
+ id: MOCK_HAZARD_AMOSITE_ID,
83350
+ code: 'AMOSITE',
83351
+ title: 'Amosite (Brown or Grey Asbestos)',
83352
+ ...withCategories([HAZARD_CATEGORY_CODES.asbestos]),
83353
+ ...withTemplate(QUESTIONNAIRE_ID_WS_HAZARD),
83354
+ status: AXPSystemStatusType.Active,
83355
+ },
83356
+ {
83357
+ id: MOCK_HAZARD_TREMOLITE_ID,
83358
+ code: 'TREMOLITE_ACTINOLITE',
83359
+ title: 'Tremolite / Actinolite',
83360
+ ...withCategories([HAZARD_CATEGORY_CODES.asbestos]),
83361
+ ...withTemplate(QUESTIONNAIRE_ID_WS_HAZARD),
83362
+ status: AXPSystemStatusType.Active,
83363
+ },
83364
+ {
83365
+ id: MOCK_HAZARD_CHLORINE_HEXIDE_ID,
83366
+ code: 'CHLORINE_HEXIDE',
83367
+ title: 'Chlorine Hexide',
83368
+ ...withCategories([HAZARD_CATEGORY_CODES.hazardousSubstance]),
83369
+ ...withTemplate(QUESTIONNAIRE_ID_WS_PPE),
83370
+ status: AXPSystemStatusType.Active,
83371
+ },
83372
+ {
83373
+ id: MOCK_HAZARD_CARBON_DIOXIDE_ID,
83374
+ code: 'CARBON_DIOXIDE',
83375
+ title: 'Carbon Dioxide',
83376
+ ...withCategories([HAZARD_CATEGORY_CODES.hazardousSubstance]),
83377
+ ...withTemplate(QUESTIONNAIRE_ID_WS_PPE),
83378
+ status: AXPSystemStatusType.Active,
83379
+ },
83380
+ {
83381
+ id: MOCK_HAZARD_ELECTROCUTION_ID,
83382
+ code: 'ELECTROCUTION',
83383
+ title: 'Electrocution',
83384
+ ...withCategories([HAZARD_CATEGORY_CODES.electricalHazard, HAZARD_CATEGORY_CODES.siteHazard]),
83385
+ ...withTemplate(QUESTIONNAIRE_ID_WS_TAKE5),
83386
+ status: AXPSystemStatusType.Active,
83387
+ },
83388
+ ];
83389
+ //#endregion
83390
+
83391
+ //#region ---- Imports ----
83392
+ //#endregion
83393
+ //#region ---- Hazard data seeder ----
83394
+ class AXMWorkplaceSafetyManagementHazardDataSeeder {
83395
+ constructor() {
83396
+ this.storage = inject(AXPEntityStorageService);
83397
+ }
83398
+ async seed() {
83399
+ await this.storage.initial(RootConfig$C.entities.hazard.source, hazardMock);
83400
+ }
83401
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXMWorkplaceSafetyManagementHazardDataSeeder, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
83402
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXMWorkplaceSafetyManagementHazardDataSeeder }); }
83403
+ }
83404
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXMWorkplaceSafetyManagementHazardDataSeeder, decorators: [{
83405
+ type: Injectable
83406
+ }] });
83407
+
83408
+ //#region ---- Imports ----
83409
+ //#endregion
83410
+ //#region ---- Stable register ids ----
83411
+ const MOCK_HAZARD_REGISTER_AMOSITE_INCIDENT_ID = 'f6a7b8c9-d0e1-4234-f567-890123456701';
83412
+ const MOCK_HAZARD_REGISTER_TREMOLITE_OBSERVATION_ID = 'f6a7b8c9-d0e1-4234-f567-890123456702';
83413
+ const MOCK_HAZARD_REGISTER_CHLORINE_ASSESSMENT_ID = 'f6a7b8c9-d0e1-4234-f567-890123456703';
83414
+ const MOCK_HAZARD_REGISTER_ELECTROCUTION_NEAR_MISS_ID = 'f6a7b8c9-d0e1-4234-f567-890123456704';
83415
+ //#endregion
83416
+ //#region ---- Helpers ----
83417
+ const withRegisterTypeCategory = (categoryCode) => {
83418
+ const category = findHazardCategoryByCode(categoryCode);
83419
+ return {
83420
+ registerType: category.id,
83421
+ registerTypeCategory: {
83422
+ id: category.id,
83423
+ title: typeof category.title === 'string' ? category.title : undefined,
83424
+ code: category.code,
83425
+ },
83426
+ };
83427
+ };
83428
+ const withHazard = (hazardId, hazard) => ({
83429
+ hazardId,
83430
+ hazard: { id: hazardId, title: hazard.title, code: hazard.code },
83431
+ });
83432
+ //#endregion
83433
+ //#region ---- Mock data ----
83434
+ const hazardRegisterMock = [
83435
+ {
83436
+ id: MOCK_HAZARD_REGISTER_AMOSITE_INCIDENT_ID,
83437
+ code: 'HR-AMOSITE-001',
83438
+ title: 'Ceiling void asbestos disturbance',
83439
+ description: 'Disturbed suspected amosite lagging during ceiling tile replacement.',
83440
+ ...withRegisterTypeCategory(HAZARD_CATEGORY_CODES.asbestos),
83441
+ ...withHazard(MOCK_HAZARD_AMOSITE_ID, {
83442
+ code: 'AMOSITE',
83443
+ title: 'Amosite (Brown or Grey Asbestos)',
83444
+ }),
83445
+ contextType: AXMHazardRegisterContextType.Site,
83446
+ contextId: 'SITE-BLDG-A-L3',
83447
+ },
83448
+ {
83449
+ id: MOCK_HAZARD_REGISTER_TREMOLITE_OBSERVATION_ID,
83450
+ code: 'HR-TREMOLITE-001',
83451
+ title: 'Fibrous material on pipe insulation',
83452
+ ...withRegisterTypeCategory(HAZARD_CATEGORY_CODES.asbestos),
83453
+ ...withHazard(MOCK_HAZARD_TREMOLITE_ID, {
83454
+ code: 'TREMOLITE_ACTINOLITE',
83455
+ title: 'Tremolite / Actinolite',
83456
+ }),
83457
+ contextType: AXMHazardRegisterContextType.Asset,
83458
+ contextId: 'ASSET-BOILER-12',
83459
+ },
83460
+ {
83461
+ id: MOCK_HAZARD_REGISTER_CHLORINE_ASSESSMENT_ID,
83462
+ code: 'HR-CHLORINE-001',
83463
+ title: 'Chlorine cylinder storage assessment',
83464
+ ...withRegisterTypeCategory(HAZARD_CATEGORY_CODES.hazardousSubstance),
83465
+ ...withHazard(MOCK_HAZARD_CHLORINE_HEXIDE_ID, {
83466
+ code: 'CHLORINE_HEXIDE',
83467
+ title: 'Chlorine Hexide',
83468
+ }),
83469
+ contextType: AXMHazardRegisterContextType.WorkOrder,
83470
+ contextId: 'WO-MAINT-24018',
83471
+ },
83472
+ {
83473
+ id: MOCK_HAZARD_REGISTER_ELECTROCUTION_NEAR_MISS_ID,
83474
+ code: 'HR-ELECTROCUTION-001',
83475
+ title: 'Energised panel near-miss',
83476
+ description: 'Technician opened panel before lockout verification.',
83477
+ ...withRegisterTypeCategory(HAZARD_CATEGORY_CODES.electricalHazard),
83478
+ ...withHazard(MOCK_HAZARD_ELECTROCUTION_ID, {
83479
+ code: 'ELECTROCUTION',
83480
+ title: 'Electrocution',
83481
+ }),
83482
+ contextType: AXMHazardRegisterContextType.Project,
83483
+ contextId: 'PRJ-PLANT-UPGRADE',
83484
+ },
83485
+ ];
83486
+ //#endregion
83487
+
83488
+ //#region ---- Imports ----
83489
+ //#endregion
83490
+ //#region ---- Hazard register seeder ----
83491
+ class AXMWorkplaceSafetyManagementHazardRegisterDataSeeder {
83492
+ constructor() {
83493
+ this.storage = inject(AXPEntityStorageService);
83494
+ }
83495
+ async seed() {
83496
+ await this.storage.initial(RootConfig$C.entities.hazardRegister.source, hazardRegisterMock);
83497
+ }
83498
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXMWorkplaceSafetyManagementHazardRegisterDataSeeder, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
83499
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXMWorkplaceSafetyManagementHazardRegisterDataSeeder }); }
83500
+ }
83501
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXMWorkplaceSafetyManagementHazardRegisterDataSeeder, decorators: [{
83502
+ type: Injectable
83503
+ }] });
83504
+
83505
+ //#region ---- Imports ----
83506
+ //#endregion
83507
+ //#region ---- Mock module ----
83508
+ class AXCWorkplaceSafetyManagementMockModule {
83509
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXCWorkplaceSafetyManagementMockModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
83510
+ static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "21.2.9", ngImport: i0, type: AXCWorkplaceSafetyManagementMockModule }); }
83511
+ static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXCWorkplaceSafetyManagementMockModule, providers: [
83512
+ { provide: AXP_DATA_SEEDER_TOKEN, useClass: AXCHazardCategorySeeder, multi: true },
83513
+ { provide: AXP_DATA_SEEDER_TOKEN, useClass: AXMWorkplaceSafetyManagementHazardDataSeeder, multi: true },
83514
+ { provide: AXP_DATA_SEEDER_TOKEN, useClass: AXMWorkplaceSafetyManagementHazardRegisterDataSeeder, multi: true },
83515
+ ] }); }
83516
+ }
83517
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXCWorkplaceSafetyManagementMockModule, decorators: [{
83518
+ type: NgModule,
83519
+ args: [{
83520
+ providers: [
83521
+ { provide: AXP_DATA_SEEDER_TOKEN, useClass: AXCHazardCategorySeeder, multi: true },
83522
+ { provide: AXP_DATA_SEEDER_TOKEN, useClass: AXMWorkplaceSafetyManagementHazardDataSeeder, multi: true },
83523
+ { provide: AXP_DATA_SEEDER_TOKEN, useClass: AXMWorkplaceSafetyManagementHazardRegisterDataSeeder, multi: true },
83524
+ ],
83525
+ }]
83526
+ }] });
83527
+
82368
83528
  class AXCMockModule {
82369
83529
  constructor(appInitService, injector) {
82370
83530
  const backendType = injector.get(AXC_ENTITY_STORAGE_BACKEND_TYPE, 'dexie');
@@ -82443,6 +83603,7 @@ class AXCMockModule {
82443
83603
  AXCProductCatalogMockModule,
82444
83604
  AXCReservationManagementMockModule,
82445
83605
  AXCMaintenanceManagementMockModule,
83606
+ AXCWorkplaceSafetyManagementMockModule,
82446
83607
  //
82447
83608
  AXCMiddlewaresModule] }); }
82448
83609
  static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXCMockModule, providers: [
@@ -82503,6 +83664,7 @@ class AXCMockModule {
82503
83664
  AXCProductCatalogMockModule,
82504
83665
  AXCReservationManagementMockModule,
82505
83666
  AXCMaintenanceManagementMockModule,
83667
+ AXCWorkplaceSafetyManagementMockModule,
82506
83668
  //
82507
83669
  AXCMiddlewaresModule] }); }
82508
83670
  }
@@ -82560,6 +83722,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
82560
83722
  AXCProductCatalogMockModule,
82561
83723
  AXCReservationManagementMockModule,
82562
83724
  AXCMaintenanceManagementMockModule,
83725
+ AXCWorkplaceSafetyManagementMockModule,
82563
83726
  //
82564
83727
  AXCMiddlewaresModule,
82565
83728
  ],
@@ -82684,5 +83847,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
82684
83847
  * Generated bundle index. Do not edit.
82685
83848
  */
82686
83849
 
82687
- export { AXCFileStorageServiceDexie as $, AXCAiChatRouterService as A, AXCAuthMockModule as B, AXCCalendarDataSeeder as C, AXCCalendarEventDataSeeder as D, AXCCalendarManagementMockModule as E, AXCCommandRegistryDataSeeder as F, AXCCommonMockModule as G, AXCContactCoreMockModule as H, AXCContentManagementMockModule as I, AXCConversationDataSeeder as J, AXCConversationMockConversationApi as K, AXCConversationMockMessageApi as L, AXCConversationMockModule as M, AXCConversationMockRealtimeApi as N, AXCConversationMockUploaderApi as O, AXCConversationMockUserApi as P, AXCCustomerManagementMockModule as Q, AXCDashboardManagementMockModule as R, AXCDataManagementMockModule as S, AXCDexieEntityStorageService as T, AXCDocumentManagementMockModule as U, AXCEditionDataSeeder as V, AXCEntityDefinitionSeederService as W, AXCEntityDefinitionsModule as X, AXCEntityStorageInsertCommand as Y, AXCEntityStorageModule as Z, AXCEntityStorageQueryQuery as _, AXMAiModelStableIds as a, AXMBusinessUnitDataSeeder as a$, AXCFileStorageServiceFirestore as a0, AXCFinancialCoreMockModule as a1, AXCFirestoreEntityStorageService as a2, AXCFormTemplateManagementMockModule as a3, AXCGoogleStrategyMock as a4, AXCHealthCoreMockModule as a5, AXCHelpDeskMockModule as a6, AXCHumanCapitalManagementMockModule as a7, AXCIdentifierManagementMockModule as a8, AXCImageCaptchaChallengeProviderMock as a9, AXCSupplierManagementMockModule as aA, AXCTaskManagementMockModule as aB, AXCTenantManagementMockModule as aC, AXCTenantSeeder as aD, AXCTextTemplateRenderBackend as aE, AXCTokensDataSeeder as aF, AXCUserPassStrategyMock as aG, AXCVersionDB as aH, AXCVersioningService as aI, AXCWidgetCatalogDataSeeder as aJ, AXCWorkflowCategorySeeder as aK, AXCWorkflowDefinitionDataSeeder as aL, AXCWorkflowEngine as aM, AXCWorkflowExecutionDB as aN, AXCWorkflowExecutionStoreDexie as aO, AXCWorkflowExecutionStoreFirestore as aP, AXCWorkflowInstanceCartableDemoSeeder as aQ, AXCWorkflowManagementMockModule as aR, AXC_ENTITY_STORAGE_BACKEND_TYPE as aS, AXC_FIRESTORE_CONFIG as aT, AXC_FIRESTORE_DB as aU, AXC_WORKFLOW_EXECUTION_STORE as aV, AXMAiDemisAssistAgentUuid as aW, AXMAiDemisAssistId as aX, AXMAiDemisGeneralAssistId as aY, AXMAiPlatformAssistantAssistId as aZ, AXMAutomationDataSeeder as a_, AXCLearningManagementMockModule as aa, AXCLocaleManagementMockModule as ab, AXCLocationManagementMockModule as ac, AXCLockService as ad, AXCMeasurementCoreMockModule as ae, AXCMeetingManagementMockModule as af, AXCMetaDataDefinitionDataSeeder as ag, AXCMetadataCategorySeeder as ah, AXCMiddlewaresModule as ai, AXCMockCaptchaChallengeComponent as aj, AXCMockEntityLogListener as ak, AXCMockModule as al, AXCMockShowMetaDataFormPopupCommand as am, AXCNotificationManagementMockModule as an, AXCOrderManagementMockModule as ao, AXCOrganizationManagementMockModule as ap, AXCPersonCoreMockModule as aq, AXCPlatformManagementMockModule as ar, AXCProcurementManagementMockModule as as, AXCProductCatalogMockModule as at, AXCProjectManagementMockModule as au, AXCQueryRegistryDataSeeder as av, AXCReportManagementMockModule as aw, AXCSecurityManagementMockModule as ax, AXCStoredEntityDefinitionLoader as ay, AXCSubscriptionManagementMockModule as az, resolveAssistSpeechModelId as b, FINANCE_ENTERPRISE as b$, AXMCalendarEventTypeSeeder as b0, AXMDashboardChartDataSourceDefinition as b1, AXMEmployeeDataSeeder as b2, AXMEmploymentTypeDataSeeder as b3, AXMFormDataSourcesProvider as b4, AXMJobDefinitionDataSeeder as b5, AXMJobLevelDataSeeder as b6, AXMLeaveRequestDataSeeder as b7, AXMMeetingDataSeeder as b8, AXMMeetingFilesDataSeeder as b9, AXPMockIdentifierService as bA, AXPMockLookupProvider as bB, AXPMockPolicyProvider as bC, AXPMockSequenceProvider as bD, AXPRoomDataSeeder as bE, AXPSecurityManagementRoleDataSeeder as bF, AXPSecurityManagementUserDataSeeder as bG, AXPTaskBoardPlatformManagementTaskProvider as bH, AXPTaskBoardProjectManagementTaskProvider as bI, AXVChangeType as bJ, BCC as bK, BOC as bL, BUSINESS_UNITS_MOCK as bM, CHAT_LAST_MESSAGE_IDS as bN, COLLABORATION_STANDARD as bO, COSTMANAGER_ENTERPRISE as bP, COSTMANAGER_PROFESSIONAL as bQ, COSTMANAGER_STANDARD as bR, CP as bS, CRM_ENTERPRISE as bT, DASHBOARDS as bU, EDITIONS as bV, EMPLOYEES_MOCK as bW, EMPLOYMENT_TYPES_MOCK as bX, ENTITY_DEFINITION_MAP as bY, ENTITY_REGISTRY as bZ, FINANCE_BASIC as b_, AXMMeetingParticipantDataSeeder as ba, AXMMeetingRoleTypeDataSeeder as bb, AXMMeetingSessionDataSeeder as bc, AXMMeetingTypeDataSeeder as bd, AXMMeetingTypeFileTemplateDataSeeder as be, AXMPositionAssignmentDataSeeder as bf, AXMPositionDataSeeder as bg, AXMQuestionBankItemCategoryDataSeeder as bh, AXMQuestionBankItemDataSeeder as bi, AXMQuestionnaireCategoryDataSeeder as bj, AXMQuestionnaireDataSeeder as bk, AXMResponsibilityDataSeeder as bl, AXMTagDataSeeder as bm, AXMTeamBusinessUnitDataSeeder as bn, AXMTeamDataSeeder as bo, AXMTeamMemberDataSeeder as bp, AXMTeamMemberRoleDataSeeder as bq, AXMWorkflowDashboardChartDataSourceDefinition as br, AXM_AI_REGISTRY_COMMAND_NAME as bs, AXM_AI_REGISTRY_QUERY_NAME as bt, AXM_CORPORATE_BUSINESS_UNIT_ID as bu, AXPDashboardDataSeeder as bv, AXPIdentifierDB as bw, AXPMessageDataSeeder as bx, AXPMockChecksumProvider as by, AXPMockClockProvider as bz, resolveDelegatedAssistOptionString as c, WS as c$, FINANCE_PRO as c0, G as c1, HR_ENTERPRISE as c2, HW as c3, JOB_DEFINITIONS_CATEGORY_MOCK as c4, JOB_DEFINITIONS_MOCK as c5, JOB_DEFINITION_CATEGORY_KEY_TO_ID as c6, JOB_LEVELS_MOCK as c7, LASER_PLUMBING_TENANT_ID as c8, LEAVE_REQUESTS_MOCK as c9, QWS as cA, RESPONSIBILITIES_CATEGORY_MOCK as cB, RESPONSIBILITIES_MOCK as cC, RESPONSIBILITY_CATEGORY_KEY_TO_ID as cD, SAFETYMINDER_BASIC as cE, SAFETYMINDER_ENTERPRISE as cF, SAFETYMINDER_PROFESSIONAL as cG, SHOP_BASIC as cH, SHOP_ENTERPRISE as cI, SHOP_PRO as cJ, TAGS_MOCK as cK, TASKS as cL, TASK_STATUSES as cM, TASK_TEMPLATES as cN, TASK_TYPES as cO, TEAMS_CATEGORY_MOCK as cP, TEAMS_MOCK as cQ, TEAM_BUSINESS_UNITS_MOCK as cR, TEAM_CATEGORY_KEY_TO_ID as cS, TEAM_MEMBERS_MOCK as cT, TEAM_MEMBER_ROLES_MOCK as cU, TIMEPLICITY_TENANT_ID as cV, TLA as cW, TOKENS as cX, TPC as cY, VISIBILITY_FILTER_BYPASS as cZ, WORKFLOW_CATEGORIES as c_, MAGFA_COMMERCE_STANDARD as ca, MAGFA_CONVERSATION_DASHBOARD as cb, MAGFA_TENANT_ID as cc, METADATA_CATEGORY_IDS as cd, METADATA_GENERAL_CATEGORY_REFS as ce, METADATA_SYSTEM_CATEGORY_REFS as cf, MLC as cg, OHR as ch, ORDERING_BASIC as ci, ORDERING_ENTERPRISE as cj, ORDERING_STANDARD as ck, OWNERSHIP_FILTER_BYPASS as cl, PLATFORM_CONSOLE as cm, PLATFORM_TENANT_ID as cn, PM as co, POSITIONS_CATEGORY_MOCK as cp, POSITIONS_MOCK as cq, POSITION_ASSIGNMENTS_MOCK as cr, QCP as cs, QGEN as ct, QHW as cu, QOHR as cv, QPM as cw, QTLE as cx, QUESTIONNAIRE_CATEGORY_MOCK as cy, QUESTION_BANK_ITEM_CATEGORY_MOCK as cz, axcSyncSingleEmployeeDenormalizedOrgFields as d, meetingParticipantMock as d$, activityCategoryMocks as d0, activityDefinitionEntityMock as d1, applyEntityDefinitionFirestoreSnapshot as d2, automationCommandMiddleware as d3, automationMock as d4, avatarInterface as d5, awaitConversationMockSharedStorage as d6, axVersionDB as d7, axWorkflowExecutionDB as d8, axcPatchEmployeeActivePrimaryBusinessUnitRefsFromRows as d9, createWorkflowDefinitionEntityMock as dA, dateInterface as dB, dateTimeInterface as dC, descriptionInterface as dD, documentFolderSyncMiddleware as dE, emailInterface as dF, enrichWorkflowGraph as dG, entityDefDb as dH, entityValidationMiddleware as dI, fileUploaderInterface as dJ, finalizeActivityCategoryItemCounts as dK, findEmployeeById as dL, folderStorageMiddleware as dM, groupOrderItemCalculatorMiddleware as dN, historyMiddleware as dO, identifierCommitMiddleware as dP, imageInterface as dQ, inspectionOkXNaInterface as dR, loadMockPropertyDefinitions as dS, lockGuardMiddleware as dT, longTextAnswerInterface as dU, lookupInterface as dV, lookupResolverMiddleware as dW, mapInterface as dX, meetingFilesMock as dY, meetingIds as dZ, meetingMock as d_, axcPatchEmployeeActivePrimaryPositionRefsFromRows as da, axcPatchEmployeeManagerRefsFromRows as db, axcResolveCommandRegistrySeedId as dc, axcResolveQueryRegistrySeedId as dd, axcResolveWidgetCatalogSeedId as de, bankCategory as df, buildEntityStorageQuickSearchFilter as dg, buildWorkflowInstanceCartableDemoRows as dh, bypassAllFilters as di, bypassOwnershipFilter as dj, bypassVisibilityFilter as dk, calendarEventMock as dl, calendarEventTypeMockData as dm, calendarMock as dn, chatMessageMock as dp, chatMock as dq, checkboxInterface as dr, childCountMiddleware as ds, clearEntityDefinitionFirestoreCollections as dt, colorInterface as du, computeDiff as dv, contactInterface as dw, conversationDemoSeedUserIds as dx, createFileCastMiddleware as dy, createWidgetLayoutConfig as dz, ACTIVITY_CATEGORIES as e, meetingRoleTypeMock as e0, meetingSessionMock as e1, meetingTimeSlotMock as e2, meetingTypeFileTemplateMock as e3, meetingTypeMock as e4, mergeDetailRelationMiddleware as e5, mergeQuickSearchIntoRequest as e6, metadataCategoryMocks as e7, mockParticipantIndexForSecurityUserId as e8, mockQuestionBankItemByName as e9, selectionListInterface as eA, sexAtBirthInterface as eB, signatureInterface as eC, signatureLoaderMiddleware as eD, statusDefaultMiddleware as eE, tagInterface as eF, tenantMocks as eG, textAreaInterface as eH, textInterface as eI, timeDurationInterface as eJ, titleInterface as eK, toUiRows as eL, toggleInterface as eM, tokenCategoryIds as eN, tokenCategoryMocks as eO, urlInterface as eP, versionInterface as eQ, visibilityFilterMiddleware as eR, workflowDefinitionEntityMock as eS, workflowDefinitionIds as eT, workflowDefinitionMock as eU, yesNoInterface as eV, mockRoleDefinitions as ea, multipleChoiceInterface as eb, multipleSelectInterface as ec, normalizeAnyFileArrayForView as ed, normalizeSnapshotFileFieldsForView as ee, numberInterface as ef, parseEntityStorageInsertData as eg, parseEntityStorageQueryRequest as eh, participantIds as ei, participantMock as ej, passwordInterface as ek, personIdentifierTypeMock as el, personIds as em, personLegalIds as en, personMock as eo, personNaturalIds as ep, phoneInterface as eq, primaryMiddleware as er, provideMockPropertySetups as es, qrcodeInterface as et, questionBankItemMock as eu, questionnaireMock as ev, ratingInterface as ew, richTextInterface as ex, scaleInterface as ey, selectInterface as ez, ACTIVITY_CATEGORY_ID_BY_KEY as f, ACTIVITY_DEFINITIONS as g, AI_ASSIST_MOCK as h, AI_MODEL_MOCK as i, APPLICATIONS as j, APPLICATION_CATEGORY_IDS as k, APPLICATION_CATEGORY_MOCKS as l, mockUsers as m, AXCActivityCategorySeeder as n, AXCActivityDefinitionSeeder as o, AXCAiAssistSeeder as p, AXCAiManagementMockModule as q, resolveDelegatedAssistOptionModel as r, AXCAiModelSeeder as s, AXCAppTermDataSeeder as t, AXCAppVersionDataSeeder as u, AXCApplicationCategoryDataSeeder as v, AXCApplicationDataSeeder as w, AXCApplicationManagementMockModule as x, AXCAssessmentManagementMockModule as y, AXCAssetManagementMockModule as z };
82688
- //# sourceMappingURL=acorex-connectivity-mock-acorex-connectivity-mock--5Xrsmgy.mjs.map
83850
+ export { AXCFileStorageServiceDexie as $, AXCAiChatRouterService as A, AXCAuthMockModule as B, AXCCalendarDataSeeder as C, AXCCalendarEventDataSeeder as D, AXCCalendarManagementMockModule as E, AXCCommandRegistryDataSeeder as F, AXCCommonMockModule as G, AXCContactCoreMockModule as H, AXCContentManagementMockModule as I, AXCConversationDataSeeder as J, AXCConversationMockConversationApi as K, AXCConversationMockMessageApi as L, AXCConversationMockModule as M, AXCConversationMockRealtimeApi as N, AXCConversationMockUploaderApi as O, AXCConversationMockUserApi as P, AXCCustomerManagementMockModule as Q, AXCDashboardManagementMockModule as R, AXCDataManagementMockModule as S, AXCDexieEntityStorageService as T, AXCDocumentManagementMockModule as U, AXCEditionDataSeeder as V, AXCEntityDefinitionSeederService as W, AXCEntityDefinitionsModule as X, AXCEntityStorageInsertCommand as Y, AXCEntityStorageModule as Z, AXCEntityStorageQueryQuery as _, AXMAiModelStableIds as a, AXMBusinessUnitDataSeeder as a$, AXCFileStorageServiceFirestore as a0, AXCFinancialCoreMockModule as a1, AXCFirestoreEntityStorageService as a2, AXCFormTemplateManagementMockModule as a3, AXCGoogleStrategyMock as a4, AXCHealthCoreMockModule as a5, AXCHelpDeskMockModule as a6, AXCHumanCapitalManagementMockModule as a7, AXCIdentifierManagementMockModule as a8, AXCImageCaptchaChallengeProviderMock as a9, AXCSupplierManagementMockModule as aA, AXCTaskManagementMockModule as aB, AXCTenantManagementMockModule as aC, AXCTenantSeeder as aD, AXCTextTemplateRenderBackend as aE, AXCTokensDataSeeder as aF, AXCUserPassStrategyMock as aG, AXCVersionDB as aH, AXCVersioningService as aI, AXCWidgetCatalogDataSeeder as aJ, AXCWorkflowCategorySeeder as aK, AXCWorkflowDefinitionDataSeeder as aL, AXCWorkflowEngine as aM, AXCWorkflowExecutionDB as aN, AXCWorkflowExecutionStoreDexie as aO, AXCWorkflowExecutionStoreFirestore as aP, AXCWorkflowInstanceCartableDemoSeeder as aQ, AXCWorkflowManagementMockModule as aR, AXC_ENTITY_STORAGE_BACKEND_TYPE as aS, AXC_FIRESTORE_CONFIG as aT, AXC_FIRESTORE_DB as aU, AXC_WORKFLOW_EXECUTION_STORE as aV, AXMAiDemisAssistAgentUuid as aW, AXMAiDemisAssistId as aX, AXMAiDemisGeneralAssistId as aY, AXMAiPlatformAssistantAssistId as aZ, AXMAutomationDataSeeder as a_, AXCLearningManagementMockModule as aa, AXCLocaleManagementMockModule as ab, AXCLocationManagementMockModule as ac, AXCLockService as ad, AXCMeasurementCoreMockModule as ae, AXCMeetingManagementMockModule as af, AXCMetaDataDefinitionDataSeeder as ag, AXCMetadataCategorySeeder as ah, AXCMiddlewaresModule as ai, AXCMockCaptchaChallengeComponent as aj, AXCMockEntityLogListener as ak, AXCMockModule as al, AXCMockShowMetaDataFormPopupCommand as am, AXCNotificationManagementMockModule as an, AXCOrderManagementMockModule as ao, AXCOrganizationManagementMockModule as ap, AXCPersonCoreMockModule as aq, AXCPlatformManagementMockModule as ar, AXCProcurementManagementMockModule as as, AXCProductCatalogMockModule as at, AXCProjectManagementMockModule as au, AXCQueryRegistryDataSeeder as av, AXCReportManagementMockModule as aw, AXCSecurityManagementMockModule as ax, AXCStoredEntityDefinitionLoader as ay, AXCSubscriptionManagementMockModule as az, resolveAssistSpeechModelId as b, FINANCE_ENTERPRISE as b$, AXMCalendarEventTypeSeeder as b0, AXMDashboardChartDataSourceDefinition as b1, AXMEmployeeDataSeeder as b2, AXMEmploymentTypeDataSeeder as b3, AXMFormDataSourcesProvider as b4, AXMJobDefinitionDataSeeder as b5, AXMJobLevelDataSeeder as b6, AXMLeaveRequestDataSeeder as b7, AXMMeetingDataSeeder as b8, AXMMeetingFilesDataSeeder as b9, AXPMockIdentifierService as bA, AXPMockLookupProvider as bB, AXPMockPolicyProvider as bC, AXPMockSequenceProvider as bD, AXPRoomDataSeeder as bE, AXPSecurityManagementRoleDataSeeder as bF, AXPSecurityManagementUserDataSeeder as bG, AXPTaskBoardPlatformManagementTaskProvider as bH, AXPTaskBoardProjectManagementTaskProvider as bI, AXVChangeType as bJ, BCC as bK, BOC as bL, BUSINESS_UNITS_MOCK as bM, CHAT_LAST_MESSAGE_IDS as bN, COLLABORATION_STANDARD as bO, COSTMANAGER_ENTERPRISE as bP, COSTMANAGER_PROFESSIONAL as bQ, COSTMANAGER_STANDARD as bR, CP as bS, CRM_ENTERPRISE as bT, DASHBOARDS as bU, EDITIONS as bV, EMPLOYEES_MOCK as bW, EMPLOYMENT_TYPES_MOCK as bX, ENTITY_DEFINITION_MAP as bY, ENTITY_REGISTRY as bZ, FINANCE_BASIC as b_, AXMMeetingParticipantDataSeeder as ba, AXMMeetingRoleTypeDataSeeder as bb, AXMMeetingSessionDataSeeder as bc, AXMMeetingTypeDataSeeder as bd, AXMMeetingTypeFileTemplateDataSeeder as be, AXMPositionAssignmentDataSeeder as bf, AXMPositionDataSeeder as bg, AXMQuestionBankItemCategoryDataSeeder as bh, AXMQuestionBankItemDataSeeder as bi, AXMQuestionnaireCategoryDataSeeder as bj, AXMQuestionnaireDataSeeder as bk, AXMResponsibilityDataSeeder as bl, AXMTagDataSeeder as bm, AXMTeamBusinessUnitDataSeeder as bn, AXMTeamDataSeeder as bo, AXMTeamMemberDataSeeder as bp, AXMTeamMemberRoleDataSeeder as bq, AXMWorkflowDashboardChartDataSourceDefinition as br, AXM_AI_REGISTRY_COMMAND_NAME as bs, AXM_AI_REGISTRY_QUERY_NAME as bt, AXM_CORPORATE_BUSINESS_UNIT_ID as bu, AXPDashboardDataSeeder as bv, AXPIdentifierDB as bw, AXPMessageDataSeeder as bx, AXPMockChecksumProvider as by, AXPMockClockProvider as bz, resolveDelegatedAssistOptionString as c, WS as c$, FINANCE_PRO as c0, G as c1, HR_ENTERPRISE as c2, HW as c3, JOB_DEFINITIONS_CATEGORY_MOCK as c4, JOB_DEFINITIONS_MOCK as c5, JOB_DEFINITION_CATEGORY_KEY_TO_ID as c6, JOB_LEVELS_MOCK as c7, LASER_PLUMBING_TENANT_ID as c8, LEAVE_REQUESTS_MOCK as c9, QWS as cA, RESPONSIBILITIES_CATEGORY_MOCK as cB, RESPONSIBILITIES_MOCK as cC, RESPONSIBILITY_CATEGORY_KEY_TO_ID as cD, SAFETYMINDER_BASIC as cE, SAFETYMINDER_ENTERPRISE as cF, SAFETYMINDER_PROFESSIONAL as cG, SHOP_BASIC as cH, SHOP_ENTERPRISE as cI, SHOP_PRO as cJ, TAGS_MOCK as cK, TASKS as cL, TASK_STATUSES as cM, TASK_TEMPLATES as cN, TASK_TYPES as cO, TEAMS_CATEGORY_MOCK as cP, TEAMS_MOCK as cQ, TEAM_BUSINESS_UNITS_MOCK as cR, TEAM_CATEGORY_KEY_TO_ID as cS, TEAM_MEMBERS_MOCK as cT, TEAM_MEMBER_ROLES_MOCK as cU, TIMEPLICITY_TENANT_ID as cV, TLA as cW, TOKENS as cX, TPC as cY, VISIBILITY_FILTER_BYPASS as cZ, WORKFLOW_CATEGORIES as c_, MAGFA_COMMERCE_STANDARD as ca, MAGFA_CONVERSATION_DASHBOARD as cb, MAGFA_TENANT_ID as cc, METADATA_CATEGORY_IDS as cd, METADATA_GENERAL_CATEGORY_REFS as ce, METADATA_SYSTEM_CATEGORY_REFS as cf, MLC as cg, OHR as ch, ORDERING_BASIC as ci, ORDERING_ENTERPRISE as cj, ORDERING_STANDARD as ck, OWNERSHIP_FILTER_BYPASS as cl, PLATFORM_CONSOLE as cm, PLATFORM_TENANT_ID as cn, PM as co, POSITIONS_CATEGORY_MOCK as cp, POSITIONS_MOCK as cq, POSITION_ASSIGNMENTS_MOCK as cr, QCP as cs, QGEN as ct, QHW as cu, QOHR as cv, QPM as cw, QTLE as cx, QUESTIONNAIRE_CATEGORY_MOCK as cy, QUESTION_BANK_ITEM_CATEGORY_MOCK as cz, axcSyncSingleEmployeeDenormalizedOrgFields as d, meetingParticipantMock as d$, activityCategoryMocks as d0, activityDefinitionEntityMock as d1, applyEntityDefinitionFirestoreSnapshot as d2, attachmentsInterface as d3, automationCommandMiddleware as d4, automationMock as d5, avatarInterface as d6, awaitConversationMockSharedStorage as d7, axVersionDB as d8, axWorkflowExecutionDB as d9, createWidgetLayoutConfig as dA, createWorkflowDefinitionEntityMock as dB, dateInterface as dC, dateTimeInterface as dD, descriptionInterface as dE, documentFolderSyncMiddleware as dF, emailInterface as dG, enrichWorkflowGraph as dH, entityDefDb as dI, entityValidationMiddleware as dJ, finalizeActivityCategoryItemCounts as dK, findEmployeeById as dL, folderStorageMiddleware as dM, groupOrderItemCalculatorMiddleware as dN, historyMiddleware as dO, identifierCommitMiddleware as dP, imageInterface as dQ, inspectionOkXNaInterface as dR, loadMockPropertyDefinitions as dS, lockGuardMiddleware as dT, longTextAnswerInterface as dU, lookupInterface as dV, lookupResolverMiddleware as dW, mapInterface as dX, meetingFilesMock as dY, meetingIds as dZ, meetingMock as d_, axcPatchEmployeeActivePrimaryBusinessUnitRefsFromRows as da, axcPatchEmployeeActivePrimaryPositionRefsFromRows as db, axcPatchEmployeeManagerRefsFromRows as dc, axcResolveCommandRegistrySeedId as dd, axcResolveQueryRegistrySeedId as de, axcResolveWidgetCatalogSeedId as df, bankCategory as dg, buildEntityStorageQuickSearchFilter as dh, buildWorkflowInstanceCartableDemoRows as di, bypassAllFilters as dj, bypassOwnershipFilter as dk, bypassVisibilityFilter as dl, calendarEventMock as dm, calendarEventTypeMockData as dn, calendarMock as dp, chatMessageMock as dq, chatMock as dr, checkboxInterface as ds, childCountMiddleware as dt, clearEntityDefinitionFirestoreCollections as du, colorInterface as dv, computeDiff as dw, contactInterface as dx, conversationDemoSeedUserIds as dy, createFileCastMiddleware as dz, ACTIVITY_CATEGORIES as e, meetingRoleTypeMock as e0, meetingSessionMock as e1, meetingTimeSlotMock as e2, meetingTypeFileTemplateMock as e3, meetingTypeMock as e4, mergeDetailRelationMiddleware as e5, mergeQuickSearchIntoRequest as e6, metadataCategoryMocks as e7, mockParticipantIndexForSecurityUserId as e8, mockQuestionBankItemByName as e9, selectionListInterface as eA, sexAtBirthInterface as eB, signatureInterface as eC, statusDefaultMiddleware as eD, tagInterface as eE, tenantMocks as eF, textAreaInterface as eG, textInterface as eH, timeDurationInterface as eI, titleInterface as eJ, toUiRows as eK, toggleInterface as eL, tokenCategoryIds as eM, tokenCategoryMocks as eN, urlInterface as eO, versionInterface as eP, visibilityFilterMiddleware as eQ, workflowDefinitionEntityMock as eR, workflowDefinitionIds as eS, workflowDefinitionMock as eT, yesNoInterface as eU, mockRoleDefinitions as ea, multipleChoiceInterface as eb, multipleSelectInterface as ec, normalizeAnyFileArrayForView as ed, normalizeSnapshotFileFieldsForView as ee, numberInterface as ef, parseEntityStorageInsertData as eg, parseEntityStorageQueryRequest as eh, participantIds as ei, participantMock as ej, passwordInterface as ek, personIdentifierTypeMock as el, personIds as em, personLegalIds as en, personMock as eo, personNaturalIds as ep, phoneInterface as eq, primaryMiddleware as er, provideMockPropertySetups as es, qrcodeInterface as et, questionBankItemMock as eu, questionnaireMock as ev, ratingInterface as ew, richTextInterface as ex, scaleInterface as ey, selectInterface as ez, ACTIVITY_CATEGORY_ID_BY_KEY as f, ACTIVITY_DEFINITIONS as g, AI_ASSIST_MOCK as h, AI_MODEL_MOCK as i, APPLICATIONS as j, APPLICATION_CATEGORY_IDS as k, APPLICATION_CATEGORY_MOCKS as l, mockUsers as m, AXCActivityCategorySeeder as n, AXCActivityDefinitionSeeder as o, AXCAiAssistSeeder as p, AXCAiManagementMockModule as q, resolveDelegatedAssistOptionModel as r, AXCAiModelSeeder as s, AXCAppTermDataSeeder as t, AXCAppVersionDataSeeder as u, AXCApplicationCategoryDataSeeder as v, AXCApplicationDataSeeder as w, AXCApplicationManagementMockModule as x, AXCAssessmentManagementMockModule as y, AXCAssetManagementMockModule as z };
83851
+ //# sourceMappingURL=acorex-connectivity-mock-acorex-connectivity-mock-0h4KR9DL.mjs.map