diff --git a/src/Abstractions/CrestApps.Core.AI.Abstractions/Models/AIChatSession.cs b/src/Abstractions/CrestApps.Core.AI.Abstractions/Models/AIChatSession.cs index e9333303..ff52179c 100644 --- a/src/Abstractions/CrestApps.Core.AI.Abstractions/Models/AIChatSession.cs +++ b/src/Abstractions/CrestApps.Core.AI.Abstractions/Models/AIChatSession.cs @@ -38,6 +38,16 @@ public sealed class AIChatSession : ExtensibleEntity, IModifiedUtcAwareModel /// public string ClientId { get; set; } + /// + /// Gets or sets the captured remote-address value for this session when plain-text or encrypted storage is enabled. + /// + public string RemoteAddress { get; set; } + + /// + /// Gets or sets the hashed remote-address signal captured for this session when enabled. + /// + public string RemoteAddressHash { get; set; } + /// /// Gets or sets the collection of document references attached to this session. /// Documents are uploaded by users and used for RAG (Retrieval-Augmented Generation). diff --git a/src/Abstractions/CrestApps.Core.AI.Abstractions/Models/AIChatSessionEvent.cs b/src/Abstractions/CrestApps.Core.AI.Abstractions/Models/AIChatSessionEvent.cs index 9e5a1e48..72ce408f 100644 --- a/src/Abstractions/CrestApps.Core.AI.Abstractions/Models/AIChatSessionEvent.cs +++ b/src/Abstractions/CrestApps.Core.AI.Abstractions/Models/AIChatSessionEvent.cs @@ -17,8 +17,7 @@ public sealed class AIChatSessionEvent : ExtensibleEntity, IModifiedUtcAwareMode public string ProfileId { get; set; } /// - /// Gets or sets the persistent anonymous visitor identifier. - /// Generated on the client side and stored in localStorage for cross-session tracking. + /// Gets or sets the persistent visitor identifier resolved by the configured visitor-identity strategy. /// public string VisitorId { get; set; } @@ -32,6 +31,16 @@ public sealed class AIChatSessionEvent : ExtensibleEntity, IModifiedUtcAwareMode /// public bool IsAuthenticated { get; set; } + /// + /// Gets or sets the captured remote-address value for this session when plain-text or encrypted storage is enabled. + /// + public string RemoteAddress { get; set; } + + /// + /// Gets or sets the hashed remote-address signal captured for this session when enabled. + /// + public string RemoteAddressHash { get; set; } + /// /// Gets or sets the UTC timestamp when the session started. /// diff --git a/src/Abstractions/CrestApps.Core.AI.Abstractions/Security/AIChatRateLimitingOptions.cs b/src/Abstractions/CrestApps.Core.AI.Abstractions/Security/AIChatRateLimitingOptions.cs new file mode 100644 index 00000000..203a6729 --- /dev/null +++ b/src/Abstractions/CrestApps.Core.AI.Abstractions/Security/AIChatRateLimitingOptions.cs @@ -0,0 +1,28 @@ +namespace CrestApps.Core.AI.Security; + +/// +/// Configures how AI chat rate-limit keys are partitioned. +/// +public sealed class AIChatRateLimitingOptions +{ + /// + /// Gets or sets the key partitions used for authenticated chat-message throttling. + /// + public ChatRateLimitPartition AuthenticatedMessagePartitions { get; set; } = ChatRateLimitPartition.AuthenticatedUser; + + /// + /// Gets or sets the key partitions used for anonymous chat-message throttling. + /// + public ChatRateLimitPartition AnonymousMessagePartitions { get; set; } = + ChatRateLimitPartition.Visitor | + ChatRateLimitPartition.NetworkAddress | + ChatRateLimitPartition.Session | + ChatRateLimitPartition.Connection; + + /// + /// Gets or sets the key partitions used for anonymous session-start throttling. + /// + public ChatRateLimitPartition AnonymousSessionStartPartitions { get; set; } = + ChatRateLimitPartition.Visitor | + ChatRateLimitPartition.NetworkAddress; +} diff --git a/src/Abstractions/CrestApps.Core.AI.Abstractions/Security/AIVisitorIdentity.cs b/src/Abstractions/CrestApps.Core.AI.Abstractions/Security/AIVisitorIdentity.cs new file mode 100644 index 00000000..b14c4353 --- /dev/null +++ b/src/Abstractions/CrestApps.Core.AI.Abstractions/Security/AIVisitorIdentity.cs @@ -0,0 +1,28 @@ +namespace CrestApps.Core.AI.Security; + +/// +/// Represents the resolved visitor identity for the current AI chat request. +/// +public sealed class AIVisitorIdentity +{ + /// + /// Gets or sets the stable visitor identifier. + /// For authenticated users this is the user identifier; for anonymous users this is a long-lived visitor token. + /// + public string VisitorId { get; set; } + + /// + /// Gets or sets a value indicating whether the visitor is authenticated. + /// + public bool IsAuthenticated { get; set; } + + /// + /// Gets or sets the hashed remote-address signal used only for abuse controls. + /// + public string RemoteAddressHash { get; set; } + + /// + /// Gets or sets the captured remote-address value when plain-text or encrypted storage is enabled. + /// + public string RemoteAddress { get; set; } +} diff --git a/src/Abstractions/CrestApps.Core.AI.Abstractions/Security/AIVisitorIdentityOptions.cs b/src/Abstractions/CrestApps.Core.AI.Abstractions/Security/AIVisitorIdentityOptions.cs new file mode 100644 index 00000000..9a536da6 --- /dev/null +++ b/src/Abstractions/CrestApps.Core.AI.Abstractions/Security/AIVisitorIdentityOptions.cs @@ -0,0 +1,29 @@ +namespace CrestApps.Core.AI.Security; + +/// +/// Configures anonymous visitor tracking for AI chat widgets and sessions. +/// +public sealed class AIVisitorIdentityOptions +{ + /// + /// Gets or sets the cookie name used to persist the anonymous visitor identifier. + /// + public string CookieName { get; set; } = "crestapps-ai-visitor"; + + /// + /// Gets or sets how long the anonymous visitor cookie remains valid. + /// + public TimeSpan CookieLifetime { get; set; } = TimeSpan.FromDays(180); + + /// + /// Gets or sets how the remote address should be captured for abuse controls and optional auditing. + /// + public AIVisitorRemoteAddressMode RemoteAddressMode { get; set; } = AIVisitorRemoteAddressMode.Hashed; + + /// + /// Gets or sets an application-specific salt used when hashing remote addresses. + /// This value is used when is set to + /// or . + /// + public string RemoteAddressHashSalt { get; set; } = "CrestApps.Core.AI.VisitorIdentity"; +} diff --git a/src/Abstractions/CrestApps.Core.AI.Abstractions/Security/AIVisitorRemoteAddressMode.cs b/src/Abstractions/CrestApps.Core.AI.Abstractions/Security/AIVisitorRemoteAddressMode.cs new file mode 100644 index 00000000..221e5b00 --- /dev/null +++ b/src/Abstractions/CrestApps.Core.AI.Abstractions/Security/AIVisitorRemoteAddressMode.cs @@ -0,0 +1,27 @@ +namespace CrestApps.Core.AI.Security; + +/// +/// Determines how the framework captures remote-address data for AI chat requests. +/// +public enum AIVisitorRemoteAddressMode +{ + /// + /// Do not capture or persist remote-address data. + /// + Disabled = 0, + + /// + /// Capture only a salted hash of the remote address for privacy-first abuse controls. + /// + Hashed = 1, + + /// + /// Capture the remote address in plain text for operational controls such as blocklists. + /// + PlainText = 2, + + /// + /// Capture the remote address in encrypted form for at-rest protection while still allowing hashed abuse partitioning. + /// + Encrypted = 3, +} diff --git a/src/Abstractions/CrestApps.Core.AI.Abstractions/Security/ChatRateLimitPartition.cs b/src/Abstractions/CrestApps.Core.AI.Abstractions/Security/ChatRateLimitPartition.cs new file mode 100644 index 00000000..f120bda6 --- /dev/null +++ b/src/Abstractions/CrestApps.Core.AI.Abstractions/Security/ChatRateLimitPartition.cs @@ -0,0 +1,38 @@ +namespace CrestApps.Core.AI.Security; + +/// +/// Identifies which request attributes participate in AI chat rate-limit partitioning. +/// +[Flags] +public enum ChatRateLimitPartition +{ + /// + /// No partitioning is applied. + /// + None = 0, + + /// + /// Partition by authenticated user identifier. + /// + AuthenticatedUser = 1 << 0, + + /// + /// Partition by the stable visitor identifier. + /// + Visitor = 1 << 1, + + /// + /// Partition by the configured remote-address representation. + /// + NetworkAddress = 1 << 2, + + /// + /// Partition by chat session identifier. + /// + Session = 1 << 3, + + /// + /// Partition by connection identifier. + /// + Connection = 1 << 4, +} diff --git a/src/Abstractions/CrestApps.Core.AI.Abstractions/Security/IAIVisitorIdentityResolver.cs b/src/Abstractions/CrestApps.Core.AI.Abstractions/Security/IAIVisitorIdentityResolver.cs new file mode 100644 index 00000000..8cbed862 --- /dev/null +++ b/src/Abstractions/CrestApps.Core.AI.Abstractions/Security/IAIVisitorIdentityResolver.cs @@ -0,0 +1,13 @@ +namespace CrestApps.Core.AI.Security; + +/// +/// Resolves the current visitor identity for AI chat requests. +/// +public interface IAIVisitorIdentityResolver +{ + /// + /// Resolves the current visitor identity for the active request context. + /// + /// The resolved visitor identity. + AIVisitorIdentity Resolve(); +} diff --git a/src/Abstractions/CrestApps.Core.AI.Abstractions/Security/IChatSessionStartRateLimiter.cs b/src/Abstractions/CrestApps.Core.AI.Abstractions/Security/IChatSessionStartRateLimiter.cs new file mode 100644 index 00000000..fcdde4c4 --- /dev/null +++ b/src/Abstractions/CrestApps.Core.AI.Abstractions/Security/IChatSessionStartRateLimiter.cs @@ -0,0 +1,23 @@ +namespace CrestApps.Core.AI.Security; + +/// +/// Provides rate limiting for creating anonymous AI chat sessions. +/// +public interface IChatSessionStartRateLimiter +{ + /// + /// Determines whether the current session-start request should be rate-limited. + /// + /// The prompt security context identifying the visitor and request. + /// The cancellation token. + /// + /// A indicating whether the request is allowed or throttled. + /// + ValueTask EvaluateAsync(PromptSecurityContext context, CancellationToken cancellationToken = default); + + /// + /// Resets the rate-limit tracking state for the provided key. + /// + /// The rate-limit key to clear. + void Reset(string key); +} diff --git a/src/Abstractions/CrestApps.Core.AI.Abstractions/Security/PromptSecurityContext.cs b/src/Abstractions/CrestApps.Core.AI.Abstractions/Security/PromptSecurityContext.cs index fa692bf9..8c83027b 100644 --- a/src/Abstractions/CrestApps.Core.AI.Abstractions/Security/PromptSecurityContext.cs +++ b/src/Abstractions/CrestApps.Core.AI.Abstractions/Security/PromptSecurityContext.cs @@ -38,4 +38,19 @@ public sealed class PromptSecurityContext /// Gets or sets the connection identifier for the current connection. /// public string ConnectionId { get; set; } + + /// + /// Gets or sets the resolved visitor identifier for the current request. + /// + public string VisitorId { get; set; } + + /// + /// Gets or sets the hashed remote-address signal used only for abuse controls. + /// + public string RemoteAddressHash { get; set; } + + /// + /// Gets or sets the captured remote-address value when plain-text or encrypted storage is enabled. + /// + public string RemoteAddress { get; set; } } diff --git a/src/Abstractions/CrestApps.Core.AI.Abstractions/Security/PromptSecurityOptions.cs b/src/Abstractions/CrestApps.Core.AI.Abstractions/Security/PromptSecurityOptions.cs index 0428de4e..3f552d4d 100644 --- a/src/Abstractions/CrestApps.Core.AI.Abstractions/Security/PromptSecurityOptions.cs +++ b/src/Abstractions/CrestApps.Core.AI.Abstractions/Security/PromptSecurityOptions.cs @@ -75,10 +75,21 @@ public sealed class PromptSecurityOptions /// Gets or sets the maximum number of messages per session that can be sent /// within the rate limit window. Set to zero to disable rate limiting. /// - public int MaxMessagesPerWindow { get; set; } + public int MaxMessagesPerWindow { get; set; } = 20; /// /// Gets or sets the rate limit window duration. /// public TimeSpan RateLimitWindow { get; set; } = TimeSpan.FromMinutes(1); + + /// + /// Gets or sets the maximum number of anonymous chat sessions that can be started + /// within the anonymous session rate-limit window. Set to zero to disable this limit. + /// + public int MaxAnonymousSessionsPerWindow { get; set; } = 5; + + /// + /// Gets or sets the anonymous session-start rate-limit window duration. + /// + public TimeSpan AnonymousSessionRateLimitWindow { get; set; } = TimeSpan.FromMinutes(10); } diff --git a/src/CrestApps.Core.Docs/docs/changelog/v1.0.0.md b/src/CrestApps.Core.Docs/docs/changelog/v1.0.0.md index 8b9f7dbc..24ed80b9 100644 --- a/src/CrestApps.Core.Docs/docs/changelog/v1.0.0.md +++ b/src/CrestApps.Core.Docs/docs/changelog/v1.0.0.md @@ -14,6 +14,8 @@ description: Initial standalone release notes for the CrestApps.Core repository. ## Highlights - ships the shared abstractions, infrastructure, AI runtime, provider integrations, and protocol packages under the `CrestApps.Core` name +- assigns stable first-party anonymous visitor IDs to AI chat sessions, uses those visitor IDs for unique-visitor analytics, makes remote-address capture configurable with privacy-first hashed defaults plus optional plain-text or encrypted-at-rest storage, protects anonymous chat session starts with shared ASP.NET Core plus hub-level rate limiting, and documents how hosts can tune thresholds or replace the default endpoint policy with their own `Microsoft.AspNetCore.RateLimiting` policy +- defers AI Profile initial-prompt persistence until the first real user prompt arrives and stops the sample chat widgets from auto-creating empty sessions on initial page load - includes a reference MVC host and an Aspire host for local composition and testing - includes a dedicated `CrestApps.Core.Tests` project for framework validation - publishes a framework-focused documentation site at [core.crestapps.com](https://core.crestapps.com) diff --git a/src/CrestApps.Core.Docs/docs/core/chat.md b/src/CrestApps.Core.Docs/docs/core/chat.md index 40a83ecc..156738b5 100644 --- a/src/CrestApps.Core.Docs/docs/core/chat.md +++ b/src/CrestApps.Core.Docs/docs/core/chat.md @@ -22,6 +22,16 @@ builder.Services.AddCrestAppsCore(crestApps => crestApps .AddAISuite(ai => ai .AddOpenAI() .AddChatInteractions(chatInteractions => chatInteractions + .ConfigureVisitorIdentity(options => + { + options.RemoteAddressMode = AIVisitorRemoteAddressMode.Hashed; + }) + .ConfigureChatRateLimiting(options => + { + options.AnonymousSessionStartPartitions = + ChatRateLimitPartition.Visitor | + ChatRateLimitPartition.NetworkAddress; + }) .AddEntityCoreStores() ) ) @@ -31,6 +41,16 @@ builder.Services.AddCrestAppsCore(crestApps => crestApps By default, connections are discovered from `CrestApps:AI:Connections` and deployments are discovered from `CrestApps:AI:Deployments`. Connection-based deployments can reference a shared `ConnectionName`, while contained-connection deployments can embed provider-specific settings directly in the deployment entry. +The chat builder also exposes options-pattern hooks for visitor identity and rate-limit partitioning. Use `ConfigureVisitorIdentity(...)` to keep the default privacy-first hashed remote-address behavior, opt into plain-text remote-address storage when your host needs operator-managed IP controls, or encrypt remote addresses at rest with ASP.NET Core Data Protection while still using a hash for throttling. Use `ConfigureChatRateLimiting(...)` to adjust which keys participate in message and session-start throttling without replacing the built-in limiter. + +By default, the framework reduces anonymous widget spam in three ways before you add a CAPTCHA or challenge provider: + +1. It issues a stable first-party visitor cookie so anonymous usage can be tracked across multiple sessions instead of treating every session as a new visitor. +2. It rate-limits prompt traffic per visitor, with optional network-address participation and session/connection fallbacks. +3. It rate-limits anonymous session starts separately, so robots cannot bypass prompt limits by creating fresh sessions repeatedly. + +For AI Profile-based chat, `AIProfileMetadata.InitialPrompt` is now persisted lazily. The framework does not save the initial assistant prompt or create a widget session on page load by default. Instead, the session and the initial prompt are committed when the first real user prompt arrives, which avoids inflating analytics with empty sessions. + When you are ready to turn an ad hoc interaction into a reusable runtime contract, move that setup into an [AI Profile](./ai-profiles.md). ### Registering Chat Interaction Stores @@ -196,7 +216,7 @@ NewAsync() SaveAsync() (inactivity / explicit close) | Stage | What Happens | |-------|-------------| -| **Creation** | `IAIChatSessionManager.NewAsync()` allocates a new `AIChatSession`, assigns a `SessionId`, sets `Status = Active`, records `CreatedUtc`, and associates it with the profile and user. | +| **Creation** | `IAIChatSessionManager.NewAsync()` allocates a new `AIChatSession`, assigns a `SessionId`, sets `Status = Active`, records `CreatedUtc`, and associates it with the profile and user. Anonymous browser sessions now receive a stable first-party visitor-backed `ClientId` so analytics and throttling can span multiple sessions from the same visitor. | | **Active Use** | Every user message updates `LastActivityUtc`. Prompts are appended via `IAIChatSessionPromptStore`. Documents may be attached to `session.Documents`. | | **Interaction Transfer** | If a response handler transfers the conversation (e.g., AI → live agent), a new `ChatInteraction` is created while the session continues. The session's `ResponseHandlerName` updates to the new handler. | | **Closure** | The session status changes to `Closed` and `ClosedAtUtc` is recorded. The shared post-close processor updates extraction state, post-session task results, resolution analysis, and conversion-goal evaluation so hosts reuse the same runtime behavior. | @@ -214,7 +234,7 @@ NewAsync() SaveAsync() (inactivity / explicit close) | `ProfileId` | `string` | Associated AI profile | | `Title` | `string` | Human-readable title (often AI-generated after the first exchange) | | `UserId` | `string` | Authenticated user who owns the session | -| `ClientId` | `string` | Anonymous client identifier (used when `UserId` is null) | +| `ClientId` | `string` | Stable anonymous visitor identifier (used when `UserId` is null) | | `Status` | `ChatSessionStatus` | `Active`, `Closed`, etc. | | `ResponseHandlerName` | `string` | Which `IChatResponseHandler` processes messages | | `Documents` | `List` | Uploaded files for RAG processing | diff --git a/src/CrestApps.Core.Docs/docs/core/prompt-security.md b/src/CrestApps.Core.Docs/docs/core/prompt-security.md index 3cb28c5d..125730b0 100644 --- a/src/CrestApps.Core.Docs/docs/core/prompt-security.md +++ b/src/CrestApps.Core.Docs/docs/core/prompt-security.md @@ -110,8 +110,21 @@ The prompt security layer is controlled by `PromptSecurityOptions`. | `EnableAuditLogging` | `true` | Records suspicious prompt or output events | | `MaxPromptLength` | `8000` | Hard limit checked before deeper detection runs | | `BlockingThreshold` | `High` | Final risk level that changes a suspicious prompt from flagged to blocked | -| `MaxMessagesPerWindow` | `0` (disabled) | Maximum messages per sliding window before rate limiting kicks in | +| `MaxMessagesPerWindow` | `20` | Maximum messages per sliding window before rate limiting kicks in | | `RateLimitWindow` | `00:01:00` | Duration of the sliding window for rate limiting | +| `MaxAnonymousSessionsPerWindow` | `5` | Maximum anonymous chat sessions that can be started per window | +| `AnonymousSessionRateLimitWindow` | `00:10:00` | Duration of the anonymous session-start rate-limit window | + +### Visitor identity and remote-address handling + +`AIVisitorIdentityOptions` controls how anonymous visitors are stabilized and how network data is captured: + +| Option | Default | What it does | +| --- | --- | --- | +| `CookieName` | `crestapps-ai-visitor` | Name of the first-party cookie used to persist anonymous visitor IDs | +| `CookieLifetime` | `180` days | Lifetime of the anonymous visitor cookie | +| `RemoteAddressMode` | `Hashed` | Chooses whether remote-address data is disabled, stored as a salted hash, stored in plain text, or encrypted at rest with Data Protection | +| `RemoteAddressHashSalt` | `CrestApps.Core.AI.VisitorIdentity` | Salt used when `RemoteAddressMode = Hashed` or `Encrypted` | ### Weighted-scoring thresholds @@ -157,12 +170,29 @@ That model lets you keep strong defaults globally while allowing carefully chose The security layer includes built-in rate limiting to prevent abuse and brute-force prompt extraction attempts. Rate limiting runs **before** the expensive regex evaluation, acting as an early short-circuit for abusive senders. +By default, spam reduction is layered: + +1. Anonymous browsers receive a stable first-party visitor cookie. +2. Prompt traffic is throttled per visitor, with optional network-address participation and session/connection fallbacks. +3. Anonymous session starts are throttled separately so attackers cannot reset prompt quotas just by creating new sessions. +4. Sample hosts also apply an ASP.NET Core endpoint policy to explicit session-start endpoints before the chat pipeline runs. + ### Configuration | Option | Default | What it does | | --- | --- | --- | -| `MaxMessagesPerWindow` | `0` (disabled) | Maximum messages allowed within the sliding window. Set to `0` to disable. | +| `MaxMessagesPerWindow` | `20` | Maximum messages allowed within the sliding window. Set to `0` to disable. | | `RateLimitWindow` | `00:01:00` (1 minute) | The sliding window duration. | +| `MaxAnonymousSessionsPerWindow` | `5` | Maximum anonymous sessions allowed within the session-start window. Set to `0` to disable. | +| `AnonymousSessionRateLimitWindow` | `00:10:00` (10 minutes) | The anonymous session-start window duration. | + +The default limiter behavior is privacy-first but configurable through `AIChatRateLimitingOptions`: + +| Option | Default | What it does | +| --- | --- | --- | +| `AuthenticatedMessagePartitions` | `AuthenticatedUser` | Keys authenticated message throttles by the signed-in user by default | +| `AnonymousMessagePartitions` | `Visitor, NetworkAddress, Session, Connection` | Keys anonymous message throttles by stable visitor ID, then the configured network-address representation, then session/connection fallbacks | +| `AnonymousSessionStartPartitions` | `Visitor, NetworkAddress` | Keys anonymous session-start throttles by stable visitor ID plus the configured network-address representation | ### Per-profile override @@ -180,16 +210,86 @@ Set `MaxMessagesPerWindow` to `0` on a profile to disable rate limiting for that ### How it works -1. The rate limiter resolves a tracking key: **user identity** (from `ClaimsPrincipal`) takes priority, then session ID, then connection ID. +1. The message rate limiter resolves one or more tracking keys from `AIChatRateLimitingOptions`. By default, authenticated requests use the user identity, and anonymous requests use the stable visitor ID plus the configured network-address representation, with session and connection fallbacks. 2. A sliding window queue tracks timestamp entries per key. 3. Expired entries (outside the window) are evicted on each evaluation. 4. If the count equals or exceeds the maximum, a `Blocked` result is returned with `rule-id = "rate-limit"` and a `RetryAfterSeconds` hint. 5. Audit logging records rate limit blocks alongside other security events. +Anonymous session creation is protected separately: + +1. Sample hosts issue a long-lived first-party visitor cookie for anonymous browsers. +2. New anonymous session starts are throttled in two layers: + - an ASP.NET Core endpoint rate-limit policy on explicit session-start routes + - a hub-level anonymous session-start limiter that uses the same visitor key and configured network-address partition +3. Remote-address handling is configurable: + - `Disabled` stores nothing + - `Hashed` stores only a salted hash for privacy-first abuse partitioning + - `PlainText` stores the raw address for operator-managed blocklists, allowlists, or investigations + - `Encrypted` stores a protected address value for at-rest confidentiality and still records a salted hash for rate limiting and abuse partitioning + ### Replacing the default implementation Register a custom `IChatRateLimiter` implementation in DI to use Redis, a database, or another distributed state store for multi-instance deployments. +You can also keep the built-in implementation and change its partitioning strategy through the options pattern: + +```csharp +builder.Services.AddCrestAppsCore(crestApps => crestApps + .AddAISuite(ai => ai + .AddOpenAI() + .AddChatInteractions(chat => chat + .ConfigureVisitorIdentity(options => + { + options.RemoteAddressMode = AIVisitorRemoteAddressMode.Hashed; + }) + .ConfigureChatRateLimiting(options => + { + options.AnonymousMessagePartitions = + ChatRateLimitPartition.Visitor | + ChatRateLimitPartition.NetworkAddress; + + options.AnonymousSessionStartPartitions = ChatRateLimitPartition.NetworkAddress; + }) + ) + ) +); +``` + +You can change the rate-limit thresholds themselves through `PromptSecurityOptions`: + +```csharp +builder.Services.Configure(options => +{ + options.MaxMessagesPerWindow = 12; + options.RateLimitWindow = TimeSpan.FromMinutes(2); + options.MaxAnonymousSessionsPerWindow = 3; + options.AnonymousSessionRateLimitWindow = TimeSpan.FromMinutes(15); +}); +``` + +If you want to keep CrestApps' endpoint wiring but supply your own ASP.NET Core rate-limit policy, disable the built-in policy registration and point the chat endpoints at your policy name: + +```csharp +builder.Services.Configure(options => +{ + options.RegisterAnonymousSessionStartPolicy = false; + options.AnonymousSessionStartPolicyName = "MyCustomChatPolicy"; +}); + +builder.Services.AddRateLimiter(options => +{ + options.AddFixedWindowLimiter("MyCustomChatPolicy", limiterOptions => + { + limiterOptions.PermitLimit = 10; + limiterOptions.Window = TimeSpan.FromMinutes(1); + limiterOptions.QueueLimit = 0; + }); +}); +``` + +That override replaces only the ASP.NET Core endpoint/hub layer. The framework's chat-aware `IChatRateLimiter` still protects prompt traffic unless you replace that service too. + ## Configuration example ```json @@ -206,6 +306,8 @@ Register a custom `IChatRateLimiter` implementation in DI to use Redis, a databa "BlockingThreshold": "High", "MaxMessagesPerWindow": 20, "RateLimitWindow": "00:01:00", + "MaxAnonymousSessionsPerWindow": 5, + "AnonymousSessionRateLimitWindow": "00:10:00", "LowRiskScoreThreshold": 10, "MediumRiskScoreThreshold": 20, "HighRiskScoreThreshold": 35, diff --git a/src/Primitives/CrestApps.Core.AI.Chat/AIAnonymousVisitorCookieMiddleware.cs b/src/Primitives/CrestApps.Core.AI.Chat/AIAnonymousVisitorCookieMiddleware.cs new file mode 100644 index 00000000..e18d10b1 --- /dev/null +++ b/src/Primitives/CrestApps.Core.AI.Chat/AIAnonymousVisitorCookieMiddleware.cs @@ -0,0 +1,40 @@ +using CrestApps.Core.AI.Security; +using Microsoft.AspNetCore.Http; + +namespace CrestApps.Core.AI.Chat; + +/// +/// Ensures anonymous browser traffic receives a stable visitor cookie for AI chat analytics and rate limiting. +/// +public sealed class AIAnonymousVisitorCookieMiddleware +{ + private readonly RequestDelegate _next; + + /// + /// Initializes a new instance of the class. + /// + /// The next middleware. + public AIAnonymousVisitorCookieMiddleware(RequestDelegate next) + { + _next = next; + } + + /// + /// Processes the current request. + /// + /// The HTTP context. + /// The visitor identity resolver. + public Task InvokeAsync(HttpContext context, IAIVisitorIdentityResolver visitorIdentityResolver) + { + ArgumentNullException.ThrowIfNull(context); + ArgumentNullException.ThrowIfNull(visitorIdentityResolver); + + if ((HttpMethods.IsGet(context.Request.Method) || HttpMethods.IsHead(context.Request.Method)) && + context.User.Identity?.IsAuthenticated != true) + { + _ = visitorIdentityResolver.Resolve(); + } + + return _next(context); + } +} diff --git a/src/Primitives/CrestApps.Core.AI.Chat/AIChatEndpointRateLimitingOptions.cs b/src/Primitives/CrestApps.Core.AI.Chat/AIChatEndpointRateLimitingOptions.cs new file mode 100644 index 00000000..f37c4ef8 --- /dev/null +++ b/src/Primitives/CrestApps.Core.AI.Chat/AIChatEndpointRateLimitingOptions.cs @@ -0,0 +1,29 @@ +using Microsoft.AspNetCore.Http; + +namespace CrestApps.Core.AI.Chat; + +/// +/// Configures the ASP.NET Core endpoint rate-limit policies used for AI chat hosts. +/// +public sealed class AIChatEndpointRateLimitingOptions +{ + /// + /// Gets or sets the policy name used for anonymous session-start endpoint throttling. + /// + public string AnonymousSessionStartPolicyName { get; set; } = ChatRateLimitPolicyNames.AnonymousSessionStart; + + /// + /// Gets or sets a value indicating whether the shared anonymous session-start policy should be registered. + /// + public bool RegisterAnonymousSessionStartPolicy { get; set; } = true; + + /// + /// Gets or sets the HTTP status code returned when a shared chat endpoint rate limit rejects a request. + /// + public int RejectionStatusCode { get; set; } = StatusCodes.Status429TooManyRequests; + + /// + /// Gets or sets the error message returned when a shared chat endpoint rate limit rejects a request. + /// + public string AnonymousSessionStartErrorMessage { get; set; } = "Too many anonymous chat requests. Please slow down and try again."; +} diff --git a/src/Primitives/CrestApps.Core.AI.Chat/ApplicationBuilderExtensions.cs b/src/Primitives/CrestApps.Core.AI.Chat/ApplicationBuilderExtensions.cs new file mode 100644 index 00000000..9ee69da2 --- /dev/null +++ b/src/Primitives/CrestApps.Core.AI.Chat/ApplicationBuilderExtensions.cs @@ -0,0 +1,20 @@ +using Microsoft.AspNetCore.Builder; + +namespace CrestApps.Core.AI.Chat; + +/// +/// Extension methods for AI chat middleware. +/// +public static class ApplicationBuilderExtensions +{ + /// + /// Adds middleware that establishes stable anonymous visitor cookies for AI chat traffic. + /// + /// The application builder. + public static IApplicationBuilder UseAIAnonymousVisitorCookie(this IApplicationBuilder app) + { + ArgumentNullException.ThrowIfNull(app); + + return app.UseMiddleware(); + } +} diff --git a/src/Primitives/CrestApps.Core.AI.Chat/ChatRateLimitPolicyNames.cs b/src/Primitives/CrestApps.Core.AI.Chat/ChatRateLimitPolicyNames.cs new file mode 100644 index 00000000..d16e22bd --- /dev/null +++ b/src/Primitives/CrestApps.Core.AI.Chat/ChatRateLimitPolicyNames.cs @@ -0,0 +1,12 @@ +namespace CrestApps.Core.AI.Chat; + +/// +/// Provides endpoint rate-limit policy names used by the sample hosts. +/// +public static class ChatRateLimitPolicyNames +{ + /// + /// Gets the policy name used for anonymous widget and session-start traffic. + /// + public const string AnonymousSessionStart = "CrestApps.Core.AI.Chat.AnonymousSessionStart"; +} diff --git a/src/Primitives/CrestApps.Core.AI.Chat/Hubs/AIChatHubCore.cs b/src/Primitives/CrestApps.Core.AI.Chat/Hubs/AIChatHubCore.cs index ba4d948b..d2f7b57a 100644 --- a/src/Primitives/CrestApps.Core.AI.Chat/Hubs/AIChatHubCore.cs +++ b/src/Primitives/CrestApps.Core.AI.Chat/Hubs/AIChatHubCore.cs @@ -281,6 +281,7 @@ protected virtual async Task ValidatePromptSecurityAsync(I return PromptSecurityResult.Safe; } + var visitorIdentity = ResolveVisitorIdentity(services); var context = new PromptSecurityContext { Prompt = prompt, @@ -289,6 +290,9 @@ protected virtual async Task ValidatePromptSecurityAsync(I Profile = profile, User = Context.User, ConnectionId = Context.ConnectionId, + VisitorId = visitorIdentity.VisitorId, + RemoteAddressHash = visitorIdentity.RemoteAddressHash, + RemoteAddress = visitorIdentity.RemoteAddress, }; return await securityService.ValidateInputAsync(context, cancellationToken); @@ -557,6 +561,15 @@ await ExecuteInScopeAsync(async services => return; } + var sessionStartLimitResult = await EvaluateSessionStartRateLimitAsync(services, profile, Context.ConnectionAborted); + + if (sessionStartLimitResult.IsThrottled) + { + await Clients.Caller.ReceiveError(GetSessionStartRateLimitMessage(sessionStartLimitResult)); + + return; + } + var chatSession = await sessionManager.NewAsync(profile, new NewAIChatSessionContext()); if (!string.IsNullOrWhiteSpace(initialResponseHandlerName)) { @@ -1130,7 +1143,20 @@ protected virtual async Task ProcessChatPromptAsync(ChannelWriter(); var handlerResolver = services.GetRequiredService(); var sessionHandlers = services.GetRequiredService>(); - var (chatSession, isNew) = await GetOrCreateSessionAsync(services, sessionId, profile, prompt); + AIChatSession chatSession; + bool isNew; + + try + { + (chatSession, isNew) = await GetOrCreateSessionAsync(services, sessionId, profile, prompt); + } + catch (InvalidOperationException ex) + { + await Clients.Caller.ReceiveError(ex.Message); + + return; + } + await Groups.AddToGroupAsync(Context.ConnectionId, GetSessionGroupName(chatSession.SessionId), cancellationToken); var utcNow = GetUtcNow(); if (IsEndedStatus(chatSession.Status)) @@ -1146,6 +1172,8 @@ protected virtual async Task ProcessChatPromptAsync(ChannelWriter(); var completionContextBuilder = services.GetRequiredService(); var completionService = services.GetRequiredService(); - (var chatSession, _) = await GetOrCreateSessionAsync(services, sessionId, parentProfile, userPrompt: profile.Name); + AIChatSession chatSession; + + try + { + (chatSession, _) = await GetOrCreateSessionAsync(services, sessionId, parentProfile, userPrompt: profile.Name); + } + catch (InvalidOperationException ex) + { + await Clients.Caller.ReceiveError(ex.Message); + + return; + } + var generatedPrompt = await aiTemplateEngine.RenderAsync(profile.PromptTemplate, new Dictionary() { ["Profile"] = profile, ["Session"] = chatSession, }, cancellationToken); var assistantMessage = new AIChatSessionPrompt { @@ -1407,6 +1447,13 @@ protected virtual async Task ProcessUtilityAsync(ChannelWriter + /// Persists the profile initial prompt for a session only when the first real user prompt arrives. + /// + /// The prompt store. + /// The active profile. + /// The chat session. + /// The cancellation token. + protected virtual async Task EnsureInitialPromptAsync( + IAIChatSessionPromptStore promptStore, + AIProfile profile, + AIChatSession chatSession, + CancellationToken cancellationToken) + { + ArgumentNullException.ThrowIfNull(promptStore); + ArgumentNullException.ThrowIfNull(profile); + ArgumentNullException.ThrowIfNull(chatSession); + + if (profile.Type != AIProfileType.Chat || + !profile.TryGet(out var profileMetadata) || + string.IsNullOrWhiteSpace(profileMetadata.InitialPrompt)) + { + return; + } + + if (await promptStore.CountAsync(chatSession.SessionId) > 0) + { + return; + } + + await promptStore.CreateAsync(new AIChatSessionPrompt + { + ItemId = GenerateId(), + SessionId = chatSession.SessionId, + Role = ChatRole.Assistant, + Title = profile.PromptSubject, + Content = profileMetadata.InitialPrompt, + CreatedUtc = chatSession.CreatedUtc, + }, cancellationToken); + } + + /// + /// Builds a session-start rate-limit message. + /// + /// The rate-limit result. + protected virtual string GetSessionStartRateLimitMessage(RateLimitResult result) + { + ArgumentNullException.ThrowIfNull(result); + + return $"Too many new chat sessions were started from this visitor. Please wait {result.RetryAfterSeconds} second(s) and try again."; + } + + private static AIVisitorIdentity ResolveVisitorIdentity(IServiceProvider services) + { + var visitorIdentityResolver = services.GetService(); + + if (visitorIdentityResolver is null) + { + return new AIVisitorIdentity(); + } + + return visitorIdentityResolver.Resolve(); + } + + private async Task EvaluateSessionStartRateLimitAsync(IServiceProvider services, AIProfile profile, CancellationToken cancellationToken) + { + var sessionStartRateLimiter = services.GetService(); + + if (sessionStartRateLimiter is null) + { + return RateLimitResult.Allowed; + } + + var visitorIdentity = ResolveVisitorIdentity(services); + + return await sessionStartRateLimiter.EvaluateAsync(new PromptSecurityContext + { + ProfileId = profile.ItemId, + Profile = profile, + User = Context.User, + ConnectionId = Context.ConnectionId, + VisitorId = visitorIdentity.VisitorId, + RemoteAddressHash = visitorIdentity.RemoteAddressHash, + RemoteAddress = visitorIdentity.RemoteAddress, + }, cancellationToken); + } + private static bool IsEndedStatus(ChatSessionStatus status) { return status is ChatSessionStatus.Closed or ChatSessionStatus.Abandoned; diff --git a/src/Primitives/CrestApps.Core.AI.Chat/Security/DefaultAIVisitorIdentityResolver.cs b/src/Primitives/CrestApps.Core.AI.Chat/Security/DefaultAIVisitorIdentityResolver.cs new file mode 100644 index 00000000..d2083716 --- /dev/null +++ b/src/Primitives/CrestApps.Core.AI.Chat/Security/DefaultAIVisitorIdentityResolver.cs @@ -0,0 +1,156 @@ +using System.Security.Claims; +using System.Security.Cryptography; +using System.Text; +using CrestApps.Core.AI.Security; +using Microsoft.AspNetCore.DataProtection; +using Microsoft.AspNetCore.Http; +using Microsoft.Extensions.Hosting; +using Microsoft.Extensions.Options; + +namespace CrestApps.Core.AI.Chat.Security; + +/// +/// Resolves stable visitor identities for AI chat requests. +/// +public sealed class DefaultAIVisitorIdentityResolver : IAIVisitorIdentityResolver +{ + private const string RemoteAddressProtectionPurpose = "CrestApps.Core.AI.VisitorIdentity.RemoteAddress"; + private readonly IHttpContextAccessor _httpContextAccessor; + private readonly IOptions _options; + private readonly IHostEnvironment _hostEnvironment; + private readonly IDataProtector _remoteAddressProtector; + + /// + /// Initializes a new instance of the class. + /// + /// The HTTP context accessor. + /// The visitor identity options. + /// The host environment. + public DefaultAIVisitorIdentityResolver( + IHttpContextAccessor httpContextAccessor, + IOptions options, + IHostEnvironment hostEnvironment, + IDataProtectionProvider dataProtectionProvider) + { + _httpContextAccessor = httpContextAccessor; + _options = options; + _hostEnvironment = hostEnvironment; + _remoteAddressProtector = dataProtectionProvider.CreateProtector( + _hostEnvironment.ApplicationName, + RemoteAddressProtectionPurpose); + } + + /// + /// Resolves the current visitor identity for the active request context. + /// + /// The resolved visitor identity. + public AIVisitorIdentity Resolve() + { + var httpContext = _httpContextAccessor.HttpContext; + + if (httpContext is null) + { + return new AIVisitorIdentity(); + } + + var userId = httpContext.User?.FindFirstValue(ClaimTypes.NameIdentifier) ?? httpContext.User?.Identity?.Name; + var isAuthenticated = !string.IsNullOrWhiteSpace(userId); + + return new AIVisitorIdentity + { + VisitorId = isAuthenticated ? userId : ResolveAnonymousVisitorId(httpContext), + IsAuthenticated = isAuthenticated, + RemoteAddress = ResolveStoredRemoteAddress(httpContext), + RemoteAddressHash = ResolveRemoteAddressHash(httpContext), + }; + } + + private string ResolveAnonymousVisitorId(HttpContext httpContext) + { + var options = _options.Value; + + if (httpContext.Request.Cookies.TryGetValue(options.CookieName, out var cookieValue) && + !string.IsNullOrWhiteSpace(cookieValue)) + { + return cookieValue; + } + + var visitorId = UniqueId.GenerateId(); + + if (!httpContext.Response.HasStarted) + { + httpContext.Response.Cookies.Append( + options.CookieName, + visitorId, + new CookieOptions + { + HttpOnly = true, + IsEssential = true, + MaxAge = options.CookieLifetime, + SameSite = SameSiteMode.Lax, + Secure = httpContext.Request.IsHttps, + }); + } + + return visitorId; + } + + private string ResolveRemoteAddressHash(HttpContext httpContext) + { + var options = _options.Value; + + if (options.RemoteAddressMode != AIVisitorRemoteAddressMode.Hashed && + options.RemoteAddressMode != AIVisitorRemoteAddressMode.Encrypted) + { + return null; + } + + var remoteAddress = ResolveRemoteAddress(httpContext); + + if (string.IsNullOrWhiteSpace(remoteAddress)) + { + return null; + } + + var payload = $"{_hostEnvironment.ApplicationName}|{options.RemoteAddressHashSalt}|{remoteAddress.Trim()}"; + var hashBytes = SHA256.HashData(Encoding.UTF8.GetBytes(payload)); + + return Convert.ToHexString(hashBytes); + } + + private string ResolveStoredRemoteAddress(HttpContext httpContext) + { + var remoteAddress = ResolveRemoteAddress(httpContext); + + if (string.IsNullOrWhiteSpace(remoteAddress)) + { + return null; + } + + var normalizedRemoteAddress = remoteAddress.Trim(); + + return _options.Value.RemoteAddressMode switch + { + AIVisitorRemoteAddressMode.PlainText => normalizedRemoteAddress, + AIVisitorRemoteAddressMode.Encrypted => _remoteAddressProtector.Protect(normalizedRemoteAddress), + _ => null, + }; + } + + private static string ResolveRemoteAddress(HttpContext httpContext) + { + var forwardedFor = httpContext.Request.Headers["X-Forwarded-For"].ToString(); + + if (!string.IsNullOrWhiteSpace(forwardedFor)) + { + var forwardedAddress = forwardedFor.Split(',')[0].Trim(); + + if (!string.IsNullOrWhiteSpace(forwardedAddress)) + { + return forwardedAddress; + } + } + + return httpContext.Connection.RemoteIpAddress?.ToString(); + } +} diff --git a/src/Primitives/CrestApps.Core.AI.Chat/ServiceCollectionExtensions.cs b/src/Primitives/CrestApps.Core.AI.Chat/ServiceCollectionExtensions.cs index 013b7389..4d30193c 100644 --- a/src/Primitives/CrestApps.Core.AI.Chat/ServiceCollectionExtensions.cs +++ b/src/Primitives/CrestApps.Core.AI.Chat/ServiceCollectionExtensions.cs @@ -1,10 +1,12 @@ using CrestApps.Core.AI.Chat.Handlers; using CrestApps.Core.AI.Chat.Models; +using CrestApps.Core.AI.Chat.Security; using CrestApps.Core.AI.Chat.Services; using CrestApps.Core.AI.Completions; using CrestApps.Core.AI.Handlers; using CrestApps.Core.AI.Models; using CrestApps.Core.AI.Orchestration; +using CrestApps.Core.AI.Security; using CrestApps.Core.AI.Services; using CrestApps.Core.Builders; using CrestApps.Core.Services; @@ -102,8 +104,12 @@ public static IServiceCollection AddCoreAIChatInteractions(this IServiceCollecti { ArgumentNullException.ThrowIfNull(services); + services.AddDataProtection(); services.TryAddSingleton(); services.TryAddSingleton(TimeProvider.System); + services.AddOptions(); + services.AddOptions(); + services.AddSingleton(); services.AddCoreAIChatNotifications(); services.AddCoreAIChatSessionProcessing(); services.TryAddScoped(); @@ -149,4 +155,38 @@ public static CrestAppsChatInteractionsBuilder ConfigureChatHubOptions(thi return builder; } + + /// + /// Configures visitor-identity handling for chat interactions. + /// + /// The builder. + /// The visitor-identity configuration action. + public static CrestAppsChatInteractionsBuilder ConfigureVisitorIdentity( + this CrestAppsChatInteractionsBuilder builder, + Action configure) + { + ArgumentNullException.ThrowIfNull(builder); + ArgumentNullException.ThrowIfNull(configure); + + builder.Services.Configure(configure); + + return builder; + } + + /// + /// Configures chat rate-limit partitioning for chat interactions. + /// + /// The builder. + /// The chat rate-limiting configuration action. + public static CrestAppsChatInteractionsBuilder ConfigureChatRateLimiting( + this CrestAppsChatInteractionsBuilder builder, + Action configure) + { + ArgumentNullException.ThrowIfNull(builder); + ArgumentNullException.ThrowIfNull(configure); + + builder.Services.Configure(configure); + + return builder; + } } diff --git a/src/Primitives/CrestApps.Core.AI.Chat/Services/DefaultAIChatSessionEventService.cs b/src/Primitives/CrestApps.Core.AI.Chat/Services/DefaultAIChatSessionEventService.cs index 57533a99..1f95ab6a 100644 --- a/src/Primitives/CrestApps.Core.AI.Chat/Services/DefaultAIChatSessionEventService.cs +++ b/src/Primitives/CrestApps.Core.AI.Chat/Services/DefaultAIChatSessionEventService.cs @@ -43,6 +43,8 @@ public async Task RecordSessionStartedAsync( VisitorId = isAuthenticated ? chatSession.UserId : chatSession.ClientId ?? string.Empty, UserId = chatSession.UserId, IsAuthenticated = isAuthenticated, + RemoteAddress = chatSession.RemoteAddress, + RemoteAddressHash = chatSession.RemoteAddressHash, SessionStartedUtc = now, MessageCount = 0, HandleTimeSeconds = 0, @@ -81,6 +83,8 @@ public async Task RecordSessionEndedAsync( VisitorId = isAuthenticated ? chatSession.UserId : chatSession.ClientId ?? string.Empty, UserId = chatSession.UserId, IsAuthenticated = isAuthenticated, + RemoteAddress = chatSession.RemoteAddress, + RemoteAddressHash = chatSession.RemoteAddressHash, SessionStartedUtc = chatSession.CreatedUtc, SessionEndedUtc = chatSession.ClosedAtUtc ?? now, MessageCount = promptCount, diff --git a/src/Primitives/CrestApps.Core.AI/Security/ChatRateLimitKeyResolver.cs b/src/Primitives/CrestApps.Core.AI/Security/ChatRateLimitKeyResolver.cs new file mode 100644 index 00000000..831eff1b --- /dev/null +++ b/src/Primitives/CrestApps.Core.AI/Security/ChatRateLimitKeyResolver.cs @@ -0,0 +1,152 @@ +using System.Security.Claims; + +namespace CrestApps.Core.AI.Security; + +/// +/// Builds consistent rate-limit partition keys for AI chat requests. +/// +public static class ChatRateLimitKeyResolver +{ + /// + /// Resolves the message-throttling keys for the provided context. + /// + /// The prompt security context. + /// The chat rate-limiting options. + /// The rate-limit keys to evaluate. + public static List ResolveMessageKeys(PromptSecurityContext context, AIChatRateLimitingOptions options) + { + ArgumentNullException.ThrowIfNull(context); + ArgumentNullException.ThrowIfNull(options); + + var authenticatedKeys = ResolveAuthenticatedKeys(context, options.AuthenticatedMessagePartitions); + + if (authenticatedKeys.Count > 0) + { + return authenticatedKeys; + } + + var anonymousKeys = ResolveAnonymousKeys(context, options.AnonymousMessagePartitions); + + return anonymousKeys.Count > 0 ? anonymousKeys : ["unknown"]; + } + + /// + /// Resolves the anonymous session-start throttling keys for the provided context. + /// + /// The prompt security context. + /// The chat rate-limiting options. + /// The rate-limit keys to evaluate. + public static List ResolveAnonymousSessionStartKeys(PromptSecurityContext context, AIChatRateLimitingOptions options) + { + ArgumentNullException.ThrowIfNull(context); + ArgumentNullException.ThrowIfNull(options); + + return ResolveAnonymousKeys(context, options.AnonymousSessionStartPartitions); + } + + /// + /// Resolves the network-address partition key for the provided visitor identity. + /// + /// The visitor identity. + /// The network-address partition key, if available. + public static string ResolveNetworkAddressKey(AIVisitorIdentity visitorIdentity) + { + ArgumentNullException.ThrowIfNull(visitorIdentity); + + if (!string.IsNullOrWhiteSpace(visitorIdentity.RemoteAddressHash)) + { + return $"ip-hash:{visitorIdentity.RemoteAddressHash}"; + } + + if (!string.IsNullOrWhiteSpace(visitorIdentity.RemoteAddress)) + { + return $"ip:{visitorIdentity.RemoteAddress}"; + } + + return null; + } + + private static List ResolveAuthenticatedKeys(PromptSecurityContext context, ChatRateLimitPartition partitions) + { + var keys = new List(); + + if (partitions.HasFlag(ChatRateLimitPartition.AuthenticatedUser)) + { + var userId = context.User?.FindFirst(ClaimTypes.NameIdentifier)?.Value ?? context.User?.Identity?.Name; + + if (!string.IsNullOrWhiteSpace(userId)) + { + keys.Add($"user:{userId}"); + } + } + + if (keys.Count > 0) + { + return keys; + } + + if (context.User?.Identity?.IsAuthenticated != true) + { + return keys; + } + + AppendAnonymousStyleKeys(keys, context, partitions); + + return keys; + } + + private static List ResolveAnonymousKeys(PromptSecurityContext context, ChatRateLimitPartition partitions) + { + var keys = new List(); + + AppendAnonymousStyleKeys(keys, context, partitions); + + return keys; + } + + private static void AppendAnonymousStyleKeys(List keys, PromptSecurityContext context, ChatRateLimitPartition partitions) + { + if (partitions.HasFlag(ChatRateLimitPartition.Visitor) && + !string.IsNullOrWhiteSpace(context.VisitorId)) + { + keys.Add($"visitor:{context.VisitorId}"); + } + + if (partitions.HasFlag(ChatRateLimitPartition.NetworkAddress)) + { + var networkAddressKey = ResolveNetworkAddressKey(context); + + if (!string.IsNullOrWhiteSpace(networkAddressKey)) + { + keys.Add(networkAddressKey); + } + } + + if (partitions.HasFlag(ChatRateLimitPartition.Session) && + !string.IsNullOrWhiteSpace(context.SessionId)) + { + keys.Add($"session:{context.SessionId}"); + } + + if (partitions.HasFlag(ChatRateLimitPartition.Connection) && + !string.IsNullOrWhiteSpace(context.ConnectionId)) + { + keys.Add($"conn:{context.ConnectionId}"); + } + } + + private static string ResolveNetworkAddressKey(PromptSecurityContext context) + { + if (!string.IsNullOrWhiteSpace(context.RemoteAddressHash)) + { + return $"ip-hash:{context.RemoteAddressHash}"; + } + + if (!string.IsNullOrWhiteSpace(context.RemoteAddress)) + { + return $"ip:{context.RemoteAddress}"; + } + + return null; + } +} diff --git a/src/Primitives/CrestApps.Core.AI/Security/DefaultChatRateLimiter.cs b/src/Primitives/CrestApps.Core.AI/Security/DefaultChatRateLimiter.cs index a3c56656..da018e41 100644 --- a/src/Primitives/CrestApps.Core.AI/Security/DefaultChatRateLimiter.cs +++ b/src/Primitives/CrestApps.Core.AI/Security/DefaultChatRateLimiter.cs @@ -1,5 +1,6 @@ using System.Collections.Concurrent; using CrestApps.Core.AI.Models; +using CrestApps.Core.Support; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; @@ -18,6 +19,7 @@ public sealed class DefaultChatRateLimiter : IChatRateLimiter { private readonly ConcurrentDictionary _windows = new(StringComparer.OrdinalIgnoreCase); private readonly TimeProvider _timeProvider; + private readonly IOptions _rateLimitingOptions; private readonly IOptions _options; private readonly ILogger _logger; @@ -29,10 +31,12 @@ public sealed class DefaultChatRateLimiter : IChatRateLimiter /// The logger. public DefaultChatRateLimiter( TimeProvider timeProvider, + IOptions rateLimitingOptions, IOptions options, ILogger logger) { _timeProvider = timeProvider; + _rateLimitingOptions = rateLimitingOptions; _options = options; _logger = logger; } @@ -59,49 +63,61 @@ public ValueTask EvaluateAsync(PromptSecurityContext context, C return ValueTask.FromResult(RateLimitResult.Allowed); } - var key = ResolveKey(context); var now = _timeProvider.GetUtcNow(); var windowStart = now - window; + var keys = ChatRateLimitKeyResolver.ResolveMessageKeys(context, _rateLimitingOptions.Value); - var entry = _windows.GetOrAdd(key, static _ => new SlidingWindowEntry()); - - int currentCount; - - lock (entry.Lock) + if (keys.Count == 0) { - // Evict timestamps outside the current window. - while (entry.Timestamps.Count > 0 && entry.Timestamps.Peek() <= windowStart) - { - entry.Timestamps.Dequeue(); - } + return ValueTask.FromResult(RateLimitResult.Allowed); + } - currentCount = entry.Timestamps.Count; + foreach (var key in keys) + { + var entry = _windows.GetOrAdd(key, static _ => new SlidingWindowEntry()); - if (currentCount >= maxMessages) + lock (entry.Lock) { - // Calculate retry-after as the time until the oldest entry expires. - var oldestInWindow = entry.Timestamps.Peek(); - var retryAfter = (int)Math.Ceiling((oldestInWindow + window - now).TotalSeconds); - - if (retryAfter < 1) + // Evict timestamps outside the current window. + while (entry.Timestamps.Count > 0 && entry.Timestamps.Peek() <= windowStart) { - retryAfter = 1; + entry.Timestamps.Dequeue(); } - _logger.LogWarning( - "Rate limit exceeded: Key={Key}, Count={Count}/{Max}, RetryAfter={RetryAfter}s, Session={SessionId}", - key, - currentCount, - maxMessages, - retryAfter, - context.SessionId); + var currentCount = entry.Timestamps.Count; - return ValueTask.FromResult(RateLimitResult.Throttled(retryAfter, currentCount, maxMessages)); + if (currentCount >= maxMessages) + { + // Calculate retry-after as the time until the oldest entry expires. + var oldestInWindow = entry.Timestamps.Peek(); + var retryAfter = (int)Math.Ceiling((oldestInWindow + window - now).TotalSeconds); + + if (retryAfter < 1) + { + retryAfter = 1; + } + + _logger.LogWarning( + "Rate limit exceeded: Key={Key}, Count={Count}/{Max}, RetryAfter={RetryAfter}s, Session={SessionId}", + key.SanitizeForLog(), + currentCount, + maxMessages, + retryAfter, + context.SessionId.SanitizeForLog()); + + return ValueTask.FromResult(RateLimitResult.Throttled(retryAfter, currentCount, maxMessages)); + } } + } - // Record this request. - entry.Timestamps.Enqueue(now); - currentCount = entry.Timestamps.Count; + foreach (var key in keys) + { + var entry = _windows.GetOrAdd(key, static _ => new SlidingWindowEntry()); + + lock (entry.Lock) + { + entry.Timestamps.Enqueue(now); + } } return ValueTask.FromResult(RateLimitResult.Allowed); @@ -119,31 +135,6 @@ public void Reset(string sessionId) } } - private static string ResolveKey(PromptSecurityContext context) - { - // Prefer user identity for keying (prevents bypass via new connections). - var userId = context.User?.FindFirst(System.Security.Claims.ClaimTypes.NameIdentifier)?.Value; - - if (!string.IsNullOrWhiteSpace(userId)) - { - return $"user:{userId}"; - } - - // Fall back to session ID (covers anonymous users). - if (!string.IsNullOrWhiteSpace(context.SessionId)) - { - return $"session:{context.SessionId}"; - } - - // Final fallback to connection ID. - if (!string.IsNullOrWhiteSpace(context.ConnectionId)) - { - return $"conn:{context.ConnectionId}"; - } - - return "unknown"; - } - private sealed class SlidingWindowEntry { public object Lock { get; } = new(); diff --git a/src/Primitives/CrestApps.Core.AI/Security/DefaultChatSessionStartRateLimiter.cs b/src/Primitives/CrestApps.Core.AI/Security/DefaultChatSessionStartRateLimiter.cs new file mode 100644 index 00000000..41275a6a --- /dev/null +++ b/src/Primitives/CrestApps.Core.AI/Security/DefaultChatSessionStartRateLimiter.cs @@ -0,0 +1,137 @@ +using System.Collections.Concurrent; +using CrestApps.Core.Support; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; + +namespace CrestApps.Core.AI.Security; + +/// +/// Default implementation of that limits +/// anonymous session creation using a sliding window. +/// +public sealed class DefaultChatSessionStartRateLimiter : IChatSessionStartRateLimiter +{ + private readonly ConcurrentDictionary _windows = new(StringComparer.OrdinalIgnoreCase); + private readonly TimeProvider _timeProvider; + private readonly IOptions _rateLimitingOptions; + private readonly IOptions _options; + private readonly ILogger _logger; + + /// + /// Initializes a new instance of the class. + /// + /// The time provider. + /// The prompt security options. + /// The logger. + public DefaultChatSessionStartRateLimiter( + TimeProvider timeProvider, + IOptions rateLimitingOptions, + IOptions options, + ILogger logger) + { + _timeProvider = timeProvider; + _rateLimitingOptions = rateLimitingOptions; + _options = options; + _logger = logger; + } + + /// + /// Determines whether the current session-start request should be rate-limited. + /// + /// The prompt security context identifying the visitor and request. + /// The cancellation token. + public ValueTask EvaluateAsync(PromptSecurityContext context, CancellationToken cancellationToken = default) + { + ArgumentNullException.ThrowIfNull(context); + + if (context.User?.Identity?.IsAuthenticated == true) + { + return ValueTask.FromResult(RateLimitResult.Allowed); + } + + var options = _options.Value; + var maxSessions = options.MaxAnonymousSessionsPerWindow; + + if (maxSessions <= 0) + { + return ValueTask.FromResult(RateLimitResult.Allowed); + } + + var keys = ChatRateLimitKeyResolver.ResolveAnonymousSessionStartKeys(context, _rateLimitingOptions.Value); + + if (keys.Count == 0) + { + return ValueTask.FromResult(RateLimitResult.Allowed); + } + + var window = options.AnonymousSessionRateLimitWindow; + var now = _timeProvider.GetUtcNow(); + var windowStart = now - window; + + foreach (var key in keys) + { + var entry = _windows.GetOrAdd(key, static _ => new SlidingWindowEntry()); + + lock (entry.Lock) + { + while (entry.Timestamps.Count > 0 && entry.Timestamps.Peek() <= windowStart) + { + entry.Timestamps.Dequeue(); + } + + var currentCount = entry.Timestamps.Count; + + if (currentCount >= maxSessions) + { + var oldestInWindow = entry.Timestamps.Peek(); + var retryAfter = (int)Math.Ceiling((oldestInWindow + window - now).TotalSeconds); + + if (retryAfter < 1) + { + retryAfter = 1; + } + + _logger.LogWarning( + "Anonymous chat session start rate limit exceeded: Key={Key}, Count={Count}/{Max}, RetryAfter={RetryAfter}s", + key.SanitizeForLog(), + currentCount, + maxSessions, + retryAfter); + + return ValueTask.FromResult(RateLimitResult.Throttled(retryAfter, currentCount, maxSessions)); + } + } + } + + foreach (var key in keys) + { + var entry = _windows.GetOrAdd(key, static _ => new SlidingWindowEntry()); + + lock (entry.Lock) + { + entry.Timestamps.Enqueue(now); + } + } + + return ValueTask.FromResult(RateLimitResult.Allowed); + } + + /// + /// Resets the rate-limit tracking state for the provided key. + /// + /// The rate-limit key to clear. + public void Reset(string key) + { + if (!string.IsNullOrWhiteSpace(key)) + { + _windows.TryRemove(key, out _); + } + } + + private sealed class SlidingWindowEntry + { + public object Lock { get; } = new(); + + public Queue Timestamps { get; } = new(); + } +} diff --git a/src/Primitives/CrestApps.Core.AI/Security/NullAIVisitorIdentityResolver.cs b/src/Primitives/CrestApps.Core.AI/Security/NullAIVisitorIdentityResolver.cs new file mode 100644 index 00000000..b27897ad --- /dev/null +++ b/src/Primitives/CrestApps.Core.AI/Security/NullAIVisitorIdentityResolver.cs @@ -0,0 +1,16 @@ +namespace CrestApps.Core.AI.Security; + +/// +/// Fallback visitor identity resolver used when a host has not enabled AI chat visitor tracking. +/// +public sealed class NullAIVisitorIdentityResolver : IAIVisitorIdentityResolver +{ + /// + /// Resolves the current visitor identity for the active request context. + /// + /// An empty visitor identity. + public AIVisitorIdentity Resolve() + { + return new AIVisitorIdentity(); + } +} diff --git a/src/Primitives/CrestApps.Core.AI/ServiceCollectionExtensions.cs b/src/Primitives/CrestApps.Core.AI/ServiceCollectionExtensions.cs index 8255b0aa..193b4655 100644 --- a/src/Primitives/CrestApps.Core.AI/ServiceCollectionExtensions.cs +++ b/src/Primitives/CrestApps.Core.AI/ServiceCollectionExtensions.cs @@ -529,9 +529,11 @@ public static OrchestratorBuilder AddOrchestrator( private static void AddPromotSecurityLayer(this IServiceCollection services) { // Prompt security services. + services.AddOptions(); services.AddOptions(); services.TryAddSingleton(); services.TryAddSingleton(); + services.TryAddSingleton(); services.TryAddEnumerable(ServiceDescriptor.Singleton()); services.TryAddEnumerable(ServiceDescriptor.Singleton()); services.TryAddEnumerable(ServiceDescriptor.Singleton()); diff --git a/src/Resources/CrestApps.AI.Resources/Assets/js/ai-chat-widget.js b/src/Resources/CrestApps.AI.Resources/Assets/js/ai-chat-widget.js index a0dc26ef..df83314b 100644 --- a/src/Resources/CrestApps.AI.Resources/Assets/js/ai-chat-widget.js +++ b/src/Resources/CrestApps.AI.Resources/Assets/js/ai-chat-widget.js @@ -634,10 +634,6 @@ window.coreAIChatWidgetBehavior = window.coreAIChatWidgetBehavior || function () app.reloadCurrentSession(); - if (config.autoCreateSession && !app.getSessionId()) { - app.startNewSession(); - } - if (config.widget.showHistoryButton && app.chatHistorySection) { var showHistoryButton = document.querySelector(config.widget.showHistoryButton); if (showHistoryButton) { diff --git a/src/Resources/CrestApps.AI.Resources/Assets/js/ai-chat.js b/src/Resources/CrestApps.AI.Resources/Assets/js/ai-chat.js index 8efdc9b3..27c6e68a 100644 --- a/src/Resources/CrestApps.AI.Resources/Assets/js/ai-chat.js +++ b/src/Resources/CrestApps.AI.Resources/Assets/js/ai-chat.js @@ -1321,8 +1321,6 @@ window.coreAIChatManager = function () { if (this.isSessionStarted) { this.reloadCurrentSession(); - } else if (config.autoCreateSession) { - this.startNewSession(); } }); @@ -2267,13 +2265,7 @@ window.coreAIChatManager = function () { this.sessionRating = null; this.messages = []; this.documents = []; - if (!config.autoCreateSession) { - this.showPlaceholder(); - } - - if (config.autoCreateSession) { - this.startNewSession(); - } + this.showPlaceholder(); if (widgetBehavior && typeof widgetBehavior.onSessionReset === 'function') { widgetBehavior.onSessionReset(this, config); @@ -2372,8 +2364,6 @@ window.coreAIChatManager = function () { const sessionId = this.getSessionId(); if (!hasWidgetConfig && sessionId) { this.loadSession(sessionId); - } else if (this.isOrchestratorAvailable() && config.autoCreateSession && !hasWidgetConfig && !sessionId) { - this.startNewSession(); } // Initialize document bar if enabled. @@ -2881,7 +2871,6 @@ window.coreAIChatManager = function () { metricsEnabled: 'data-coreai-chat-metrics-enabled', textToSpeechEnabled: 'data-coreai-chat-text-to-speech-enabled', sessionDocumentsEnabled: 'data-coreai-chat-session-documents-enabled', - autoCreateSession: 'data-coreai-chat-auto-create-session', singleResponseMode: 'data-coreai-chat-single-response-mode', }; diff --git a/src/Resources/CrestApps.AI.Resources/wwwroot/scripts/ai-chat-widget.js b/src/Resources/CrestApps.AI.Resources/wwwroot/scripts/ai-chat-widget.js index 9a9deb51..1c042d57 100644 --- a/src/Resources/CrestApps.AI.Resources/wwwroot/scripts/ai-chat-widget.js +++ b/src/Resources/CrestApps.AI.Resources/wwwroot/scripts/ai-chat-widget.js @@ -497,9 +497,6 @@ window.coreAIChatWidgetBehavior = window.coreAIChatWidgetBehavior || function () window.addEventListener('resize', app.widgetViewportResizeHandler); } app.reloadCurrentSession(); - if (config.autoCreateSession && !app.getSessionId()) { - app.startNewSession(); - } if (config.widget.showHistoryButton && app.chatHistorySection) { var showHistoryButton = document.querySelector(config.widget.showHistoryButton); if (showHistoryButton) { diff --git a/src/Resources/CrestApps.AI.Resources/wwwroot/scripts/ai-chat-widget.js.map b/src/Resources/CrestApps.AI.Resources/wwwroot/scripts/ai-chat-widget.js.map index be35c8e3..3967a825 100644 --- a/src/Resources/CrestApps.AI.Resources/wwwroot/scripts/ai-chat-widget.js.map +++ b/src/Resources/CrestApps.AI.Resources/wwwroot/scripts/ai-chat-widget.js.map @@ -1 +1 @@ -{"version":3,"sources":["ai-chat-widget.js"],"names":["clampWidgetValue","value","min","max","Math","window","coreAIChatWidgetBehavior","parsePixelValue","Number","isFinite","parsed","parseFloat","attach","app","config","__aiChatWidgetAttached","chatWidgetStateName","chatWidgetStateSession","chatWidgetStateDocuments","chatWidgetLayoutKey","chatHistorySection","widgetContainerElement","widgetToggleButtonElement","widgetResetSizeButtonElement","widgetResizeObserver","widgetViewportResizeHandler","widgetDefaultWidth","widgetDefaultHeight","widgetIsInitialized","getStoredWidgetLayout","widget","persistLayout","storedLayout","localStorage","getItem","JSON","parse","error","console","warn","saveStoredWidgetLayout","partialLayout","currentLayout","nextLayout","Object","assign","panel","undefined","position","setItem","stringify","getElementSize","element","fallbackWidth","fallbackHeight","width","height","rect","getBoundingClientRect","computed","getComputedStyle","round","getElementPosition","left","top","inlineLeft","style","inlineTop","computedLeft","computedTop","isHidden","display","getAvailableWidgetPositionRange","viewportPadding","padding","maxLeft","innerWidth","maxTop","innerHeight","createStoredPosition","range","leftSpan","topSpan","leftRatio","topRatio","resolveStoredPosition","storedPosition","clampWidgetPosition","getStoredWidgetDocuments","clearStoredWidgetDocuments","saveStoredWidgetDocuments","removeItem","applyAbsolutePosition","right","bottom","getWidgetDefaultSize","defaultWidth","defaultHeight","getWidgetToggleGap","isWidgetPanelVisible","classList","contains","persistWidgetPanelPosition","panelDefaultSize","panelPosition","panelSize","toggleSize","linkedPosition","persistWidgetTogglePosition","togglePosition","persistWidgetPanelSize","enableResizing","defaultSize","currentSize","abs","syncTogglePositionToPanel","syncPanelPositionToToggle","updateWidgetResetSizeButtonVisibility","add","isResized","toggle","resetWidgetSize","removeProperty","constrainWidgetElementsToViewport","restoreWidgetLayout","storedTogglePosition","enableDragging","attachDraggableWidgetElement","handle","layoutKey","suppressClickOnDrag","activePointerId","startX","startY","startLeft","startTop","dragged","dragThreshold","interactiveSelector","self","stopDragging","event","pointerId","document","removeEventListener","onPointerMove","remove","dataset","dragSuppressClick","setTimeout","deltaX","clientX","deltaY","clientY","hypot","nextPosition","addEventListener","button","target","closest","setPointerCapture","preventDefault","clampedPanel","clampedToggle","showChatScreen","initialize","chatWidgetContainer","querySelector","toggleButtonSelector","resetSizeButtonSelector","documents","minWidth","minHeight","ResizeObserver","observe","dragHandleSelector","dragHandle","reloadCurrentSession","autoCreateSession","getSessionId","startNewSession","showHistoryButton","closeHistoryButton","newChatButton","resetSession","resolveSessionId","onSessionInitialized","sessionId","onSessionReset","onDocumentsChanged","handleReceiveError","isSessionStarted","_attemptedSessionRecovery","dispose","disconnect","onMounted","onBeforeUnmount","coreAIChatWidgetManager","getAttributeValue","attributeName","getAttribute","parseBooleanAttributeValue","normalized","String","trim","toLowerCase","parseJsonAttribute","description","rawValue","buildOptionsFromDataAttributes","widgetContainerSelector","chatConfig","coreAIChatManager","buildConfigFromElement","allowWidgetHost","profileId","profileName","profileDisplayText","profileWelcomeMessage","profileChatMode","profileTtsVoiceName","profileMetricsEnabled","profileSessionDocuments","profile","id","name","displayText","welcomeMessage","chatMode","ttsVoiceName","enableSessionMetrics","allowSessionDocuments","shellSelector","closeButtonSelector","inputSelector","messageTemplateSelector","indicatorTemplateSelector","widgetStateName","openStateValue","closedStateValue","openIconHtml","closedIconHtml","options","configElementSelector","configElement","messageTemplate","innerHTML","indicatorTemplate","shell","widgetContainer","toggleButton","closeButton","profileInput","widgetOpenStateKey","widgetLayoutKey","setAttribute","layout","panelLayout","toggleLeft","toggleTop","isOpen","deferReveal","initialOpen","panelWidth","panelHeight","toggleGap","visibility","widgetApp","applySessionProfilePatch","crestAppsAIChat","patchSessionProfileSync","revealShell","syncOpenPanelPosition","updateTtsPlaybackButtons","buttons","querySelectorAll","forEach","buttonIndex","isPlaying","ttsPlayingMessageIndex","queueTtsPlaybackButtonUpdate","requestAnimationFrame","revealShellWhenStable","hasRevealed","resizeObserver","finalizeReveal","lastWidth","lastHeight","stablePasses","entries","entry","contentRect","setWidgetOpen","isCurrentlyOpen","renderPendingCharts","$watch","initializeFromElement","coreAiChatWidgetInitialized","__coreAIChatWidgetApp","jsonOptions","attributeOptions","scanForAutoInitialization","root","matches","startAutoInitialization","MutationObserver","observer","mutations","mutation","addedNodes","node","nodeType","body","childList","subtree","readyState","once"],"mappings":"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","file":"ai-chat-widget.js","sourcesContent":["function clampWidgetValue(value, min, max) {\n return Math.min(Math.max(value, min), max);\n}\n\nwindow.coreAIChatWidgetBehavior = window.coreAIChatWidgetBehavior || function () {\n function parsePixelValue(value) {\n if (typeof value === 'number' && Number.isFinite(value)) {\n return value;\n }\n\n if (typeof value !== 'string') {\n return null;\n }\n\n var parsed = parseFloat(value);\n return Number.isFinite(parsed) ? parsed : null;\n }\n\n function attach(app, config) {\n if (!app || app.__aiChatWidgetAttached) {\n return;\n }\n\n app.__aiChatWidgetAttached = true;\n app.chatWidgetStateName = null;\n app.chatWidgetStateSession = null;\n app.chatWidgetStateDocuments = null;\n app.chatWidgetLayoutKey = null;\n app.chatHistorySection = null;\n app.widgetContainerElement = null;\n app.widgetToggleButtonElement = null;\n app.widgetResetSizeButtonElement = null;\n app.widgetResizeObserver = null;\n app.widgetViewportResizeHandler = null;\n app.widgetDefaultWidth = null;\n app.widgetDefaultHeight = null;\n app.widgetIsInitialized = false;\n\n app.getStoredWidgetLayout = function () {\n if (!this.chatWidgetLayoutKey || !config.widget.persistLayout) {\n return {};\n }\n\n try {\n var storedLayout = localStorage.getItem(this.chatWidgetLayoutKey);\n return storedLayout ? JSON.parse(storedLayout) || {} : {};\n }\n catch (error) {\n console.warn('Failed to read widget layout state.', error);\n return {};\n }\n };\n\n app.saveStoredWidgetLayout = function (partialLayout) {\n if (!this.chatWidgetLayoutKey || !config.widget.persistLayout) {\n return;\n }\n\n var currentLayout = this.getStoredWidgetLayout();\n var nextLayout = Object.assign({}, currentLayout);\n\n if (partialLayout.panel !== undefined) {\n nextLayout.panel = Object.assign({}, currentLayout.panel || {}, partialLayout.panel || {});\n }\n\n if (partialLayout.position !== undefined) {\n nextLayout.position = Object.assign({}, currentLayout.position || {}, partialLayout.position || {});\n }\n\n localStorage.setItem(this.chatWidgetLayoutKey, JSON.stringify(nextLayout));\n };\n\n app.getElementSize = function (element, fallbackWidth, fallbackHeight) {\n if (!element) {\n return {\n width: fallbackWidth || 0,\n height: fallbackHeight || 0\n };\n }\n\n var rect = element.getBoundingClientRect();\n var computed = window.getComputedStyle(element);\n\n return {\n width: Math.round(rect.width || parsePixelValue(computed.width) || fallbackWidth || 0),\n height: Math.round(rect.height || parsePixelValue(computed.height) || fallbackHeight || 0)\n };\n };\n\n app.getElementPosition = function (element) {\n if (!element) {\n return {\n left: 0,\n top: 0\n };\n }\n\n var rect = element.getBoundingClientRect();\n var computed = window.getComputedStyle(element);\n var inlineLeft = parsePixelValue(element.style.left);\n var inlineTop = parsePixelValue(element.style.top);\n var computedLeft = parsePixelValue(computed.left);\n var computedTop = parsePixelValue(computed.top);\n var isHidden = computed.display === 'none';\n\n return {\n left: Math.round(isHidden && Number.isFinite(inlineLeft) ? inlineLeft : rect.left || inlineLeft || computedLeft || 0),\n top: Math.round(isHidden && Number.isFinite(inlineTop) ? inlineTop : rect.top || inlineTop || computedTop || 0)\n };\n };\n\n app.getAvailableWidgetPositionRange = function (width, height) {\n var viewportPadding = 8;\n return {\n padding: viewportPadding,\n maxLeft: Math.max(viewportPadding, window.innerWidth - width - viewportPadding),\n maxTop: Math.max(viewportPadding, window.innerHeight - height - viewportPadding)\n };\n };\n\n app.createStoredPosition = function (left, top, width, height) {\n var range = this.getAvailableWidgetPositionRange(width, height);\n var leftSpan = Math.max(0, range.maxLeft - range.padding);\n var topSpan = Math.max(0, range.maxTop - range.padding);\n\n return {\n left: Math.round(left),\n top: Math.round(top),\n leftRatio: leftSpan === 0 ? 0 : (left - range.padding) / leftSpan,\n topRatio: topSpan === 0 ? 0 : (top - range.padding) / topSpan\n };\n };\n\n app.resolveStoredPosition = function (storedPosition, width, height) {\n if (!storedPosition) {\n return null;\n }\n\n var range = this.getAvailableWidgetPositionRange(width, height);\n var left = Number(storedPosition.left);\n var top = Number(storedPosition.top);\n var leftRatio = Number(storedPosition.leftRatio);\n var topRatio = Number(storedPosition.topRatio);\n\n if (Number.isFinite(leftRatio)) {\n left = range.padding + Math.max(0, range.maxLeft - range.padding) * leftRatio;\n }\n\n if (Number.isFinite(topRatio)) {\n top = range.padding + Math.max(0, range.maxTop - range.padding) * topRatio;\n }\n\n if (!Number.isFinite(left) || !Number.isFinite(top)) {\n return null;\n }\n\n return this.clampWidgetPosition(left, top, width, height);\n };\n\n app.clampWidgetPosition = function (left, top, width, height) {\n var range = this.getAvailableWidgetPositionRange(width, height);\n\n return {\n left: Math.round(clampWidgetValue(left, range.padding, range.maxLeft)),\n top: Math.round(clampWidgetValue(top, range.padding, range.maxTop))\n };\n };\n\n app.getStoredWidgetDocuments = function () {\n this.clearStoredWidgetDocuments();\n return [];\n };\n\n app.saveStoredWidgetDocuments = function () {\n this.clearStoredWidgetDocuments();\n };\n\n app.clearStoredWidgetDocuments = function () {\n if (!this.chatWidgetStateDocuments) {\n return;\n }\n\n localStorage.removeItem(this.chatWidgetStateDocuments);\n };\n\n app.applyAbsolutePosition = function (element, left, top) {\n if (!element) {\n return;\n }\n\n element.style.left = left + 'px';\n element.style.top = top + 'px';\n element.style.right = 'auto';\n element.style.bottom = 'auto';\n };\n\n app.getWidgetDefaultSize = function () {\n return {\n width: this.widgetDefaultWidth || parsePixelValue(config.widget.defaultWidth) || 380,\n height: this.widgetDefaultHeight || parsePixelValue(config.widget.defaultHeight) || 520\n };\n };\n\n app.getWidgetToggleGap = function () {\n return 8;\n };\n\n app.isWidgetPanelVisible = function () {\n if (!this.widgetContainerElement) {\n return false;\n }\n\n var computed = window.getComputedStyle(this.widgetContainerElement);\n return this.widgetContainerElement.classList.contains('open') && computed.display !== 'none';\n };\n\n app.persistWidgetPanelPosition = function () {\n if (!this.widgetContainerElement || !config.widget.persistLayout) {\n return;\n }\n\n var panelDefaultSize = this.getWidgetDefaultSize();\n var panelPosition = this.getElementPosition(this.widgetContainerElement);\n var panelSize = this.getElementSize(this.widgetContainerElement, panelDefaultSize.width, panelDefaultSize.height);\n var toggleSize = this.getElementSize(this.widgetToggleButtonElement, 52, 52);\n var linkedPosition = this.clampWidgetPosition(\n panelPosition.left + panelSize.width - toggleSize.width,\n panelPosition.top + panelSize.height + this.getWidgetToggleGap(),\n toggleSize.width,\n toggleSize.height);\n\n this.saveStoredWidgetLayout({ position: this.createStoredPosition(linkedPosition.left, linkedPosition.top, toggleSize.width, toggleSize.height) });\n };\n\n app.persistWidgetTogglePosition = function () {\n if (!this.widgetToggleButtonElement || !config.widget.persistLayout) {\n return;\n }\n\n var togglePosition = this.getElementPosition(this.widgetToggleButtonElement);\n var toggleSize = this.getElementSize(this.widgetToggleButtonElement, 52, 52);\n this.saveStoredWidgetLayout({ position: this.createStoredPosition(togglePosition.left, togglePosition.top, toggleSize.width, toggleSize.height) });\n };\n\n app.persistWidgetPanelSize = function () {\n if (!this.widgetContainerElement || !config.widget.enableResizing || !config.widget.persistLayout) {\n return;\n }\n\n var defaultSize = this.getWidgetDefaultSize();\n var currentSize = this.getElementSize(this.widgetContainerElement, defaultSize.width, defaultSize.height);\n\n this.saveStoredWidgetLayout({\n panel: {\n width: Math.abs(currentSize.width - defaultSize.width) <= 1 ? null : currentSize.width,\n height: Math.abs(currentSize.height - defaultSize.height) <= 1 ? null : currentSize.height\n }\n });\n };\n\n app.syncTogglePositionToPanel = function (persistLayout) {\n if (persistLayout === undefined) {\n persistLayout = true;\n }\n\n if (!this.widgetContainerElement || !this.widgetToggleButtonElement) {\n return;\n }\n\n var panelDefaultSize = this.getWidgetDefaultSize();\n var panelSize = this.getElementSize(this.widgetContainerElement, panelDefaultSize.width, panelDefaultSize.height);\n var toggleSize = this.getElementSize(this.widgetToggleButtonElement, 52, 52);\n var panelPosition = this.getElementPosition(this.widgetContainerElement);\n var linkedPosition = this.clampWidgetPosition(\n panelPosition.left + panelSize.width - toggleSize.width,\n panelPosition.top + panelSize.height + this.getWidgetToggleGap(),\n toggleSize.width,\n toggleSize.height);\n\n this.applyAbsolutePosition(this.widgetToggleButtonElement, linkedPosition.left, linkedPosition.top);\n\n if (persistLayout && config.widget.persistLayout) {\n this.persistWidgetTogglePosition();\n }\n };\n\n app.syncPanelPositionToToggle = function (persistLayout) {\n if (persistLayout === undefined) {\n persistLayout = true;\n }\n\n if (!this.widgetContainerElement || !this.widgetToggleButtonElement) {\n return;\n }\n\n var panelDefaultSize = this.getWidgetDefaultSize();\n var panelSize = this.getElementSize(this.widgetContainerElement, panelDefaultSize.width, panelDefaultSize.height);\n var toggleSize = this.getElementSize(this.widgetToggleButtonElement, 52, 52);\n var togglePosition = this.getElementPosition(this.widgetToggleButtonElement);\n var linkedPosition = this.clampWidgetPosition(\n togglePosition.left + toggleSize.width - panelSize.width,\n togglePosition.top - panelSize.height - this.getWidgetToggleGap(),\n panelSize.width,\n panelSize.height);\n\n this.applyAbsolutePosition(this.widgetContainerElement, linkedPosition.left, linkedPosition.top);\n\n if (persistLayout && config.widget.persistLayout) {\n this.persistWidgetPanelPosition();\n }\n };\n\n app.updateWidgetResetSizeButtonVisibility = function () {\n if (!this.widgetResetSizeButtonElement) {\n return;\n }\n\n if (!config.widget.enableResizing || !this.widgetContainerElement) {\n this.widgetResetSizeButtonElement.classList.add('d-none');\n return;\n }\n\n var defaultSize = this.getWidgetDefaultSize();\n var currentSize = this.getElementSize(this.widgetContainerElement, defaultSize.width, defaultSize.height);\n var isResized =\n Math.abs(currentSize.width - defaultSize.width) > 1 ||\n Math.abs(currentSize.height - defaultSize.height) > 1 ||\n !!this.widgetContainerElement.style.width ||\n !!this.widgetContainerElement.style.height;\n\n this.widgetResetSizeButtonElement.classList.toggle('d-none', !isResized);\n };\n\n app.resetWidgetSize = function () {\n if (!this.widgetContainerElement || !config.widget.enableResizing) {\n return;\n }\n\n this.widgetContainerElement.style.removeProperty('width');\n this.widgetContainerElement.style.removeProperty('height');\n this.persistWidgetPanelSize();\n this.constrainWidgetElementsToViewport();\n this.updateWidgetResetSizeButtonVisibility();\n };\n\n app.restoreWidgetLayout = function () {\n var storedLayout = this.getStoredWidgetLayout();\n\n if (this.widgetContainerElement && config.widget.enableResizing) {\n if (Number.isFinite(storedLayout.panel && storedLayout.panel.width)) {\n this.widgetContainerElement.style.width = storedLayout.panel.width + 'px';\n }\n else {\n this.widgetContainerElement.style.removeProperty('width');\n }\n\n if (Number.isFinite(storedLayout.panel && storedLayout.panel.height)) {\n this.widgetContainerElement.style.height = storedLayout.panel.height + 'px';\n }\n else {\n this.widgetContainerElement.style.removeProperty('height');\n }\n }\n\n var toggleSize = this.getElementSize(this.widgetToggleButtonElement, 52, 52);\n var storedTogglePosition = this.resolveStoredPosition(storedLayout.position, toggleSize.width, toggleSize.height);\n if (this.widgetToggleButtonElement && config.widget.enableDragging && storedTogglePosition) {\n this.applyAbsolutePosition(this.widgetToggleButtonElement, storedTogglePosition.left, storedTogglePosition.top);\n this.syncPanelPositionToToggle(false);\n }\n else if (this.widgetToggleButtonElement && config.widget.enableDragging &&\n Number.isFinite(storedLayout.toggle && storedLayout.toggle.left) &&\n Number.isFinite(storedLayout.toggle && storedLayout.toggle.top)) {\n this.applyAbsolutePosition(this.widgetToggleButtonElement, storedLayout.toggle.left, storedLayout.toggle.top);\n this.syncPanelPositionToToggle(false);\n }\n else if (this.widgetContainerElement && config.widget.enableDragging &&\n Number.isFinite(storedLayout.panel && storedLayout.panel.left) &&\n Number.isFinite(storedLayout.panel && storedLayout.panel.top)) {\n this.applyAbsolutePosition(this.widgetContainerElement, storedLayout.panel.left, storedLayout.panel.top);\n this.syncTogglePositionToPanel(false);\n }\n\n this.constrainWidgetElementsToViewport();\n this.updateWidgetResetSizeButtonVisibility();\n };\n\n app.attachDraggableWidgetElement = function (element, handle, layoutKey, suppressClickOnDrag) {\n if (!element || !handle || !config.widget.enableDragging) {\n return;\n }\n\n var activePointerId = null;\n var startX = 0;\n var startY = 0;\n var startLeft = 0;\n var startTop = 0;\n var dragged = false;\n var dragThreshold = 4;\n var interactiveSelector = 'button, a, input, textarea, select, option, label';\n var self = this;\n\n function stopDragging(event) {\n if (activePointerId === null) {\n return;\n }\n\n if (event && event.pointerId !== undefined && event.pointerId !== activePointerId) {\n return;\n }\n\n document.removeEventListener('pointermove', onPointerMove);\n document.removeEventListener('pointerup', stopDragging);\n document.removeEventListener('pointercancel', stopDragging);\n element.classList.remove('ai-chat-widget-dragging');\n activePointerId = null;\n\n if (!dragged) {\n return;\n }\n\n if (layoutKey === 'panel') {\n self.syncTogglePositionToPanel(false);\n self.persistWidgetPanelPosition();\n }\n else if (layoutKey === 'toggle') {\n self.syncPanelPositionToToggle(false);\n self.persistWidgetTogglePosition();\n }\n\n if (config.widget.persistLayout) {\n self.persistWidgetPanelPosition();\n self.persistWidgetTogglePosition();\n }\n\n if (suppressClickOnDrag) {\n element.dataset.dragSuppressClick = 'true';\n window.setTimeout(function () {\n if (element.dataset.dragSuppressClick === 'true') {\n element.dataset.dragSuppressClick = 'false';\n }\n }, 0);\n }\n }\n\n function onPointerMove(event) {\n if (activePointerId === null || event.pointerId !== activePointerId) {\n return;\n }\n\n var deltaX = event.clientX - startX;\n var deltaY = event.clientY - startY;\n\n if (!dragged && Math.hypot(deltaX, deltaY) < dragThreshold) {\n return;\n }\n\n dragged = true;\n\n var defaultSize = self.getWidgetDefaultSize();\n var currentSize = self.getElementSize(\n element,\n layoutKey === 'panel' ? defaultSize.width : 52,\n layoutKey === 'panel' ? defaultSize.height : 52);\n var nextPosition = self.clampWidgetPosition(startLeft + deltaX, startTop + deltaY, currentSize.width, currentSize.height);\n\n self.applyAbsolutePosition(element, nextPosition.left, nextPosition.top);\n\n if (layoutKey === 'panel') {\n self.syncTogglePositionToPanel(false);\n }\n else if (layoutKey === 'toggle') {\n self.syncPanelPositionToToggle(false);\n }\n }\n\n handle.addEventListener('pointerdown', function (event) {\n if (event.button !== 0) {\n return;\n }\n\n if (layoutKey === 'panel' && event.target.closest(interactiveSelector)) {\n return;\n }\n\n var rect = element.getBoundingClientRect();\n startX = event.clientX;\n startY = event.clientY;\n startLeft = rect.left;\n startTop = rect.top;\n dragged = false;\n activePointerId = event.pointerId;\n element.classList.add('ai-chat-widget-dragging');\n\n if (handle.setPointerCapture) {\n handle.setPointerCapture(event.pointerId);\n }\n\n document.addEventListener('pointermove', onPointerMove);\n document.addEventListener('pointerup', stopDragging);\n document.addEventListener('pointercancel', stopDragging);\n event.preventDefault();\n });\n };\n\n app.constrainWidgetElementsToViewport = function () {\n if (this.widgetContainerElement && this.widgetContainerElement.style.left && this.isWidgetPanelVisible()) {\n var panelDefaultSize = this.getWidgetDefaultSize();\n var panelSize = this.getElementSize(this.widgetContainerElement, panelDefaultSize.width, panelDefaultSize.height);\n var panelPosition = this.getElementPosition(this.widgetContainerElement);\n var clampedPanel = this.clampWidgetPosition(panelPosition.left, panelPosition.top, panelSize.width, panelSize.height);\n\n this.applyAbsolutePosition(this.widgetContainerElement, clampedPanel.left, clampedPanel.top);\n this.syncTogglePositionToPanel(false);\n\n if (config.widget.persistLayout) {\n this.persistWidgetPanelPosition();\n this.persistWidgetTogglePosition();\n }\n }\n else if (this.widgetToggleButtonElement && this.widgetToggleButtonElement.style.left) {\n var toggleSize = this.getElementSize(this.widgetToggleButtonElement, 52, 52);\n var togglePosition = this.getElementPosition(this.widgetToggleButtonElement);\n var clampedToggle = this.clampWidgetPosition(togglePosition.left, togglePosition.top, toggleSize.width, toggleSize.height);\n\n this.applyAbsolutePosition(this.widgetToggleButtonElement, clampedToggle.left, clampedToggle.top);\n this.syncPanelPositionToToggle(false);\n\n if (config.widget.persistLayout) {\n this.persistWidgetTogglePosition();\n this.persistWidgetPanelPosition();\n }\n }\n };\n\n app.showChatScreen = function () {\n if (!this.chatHistorySection) {\n return;\n }\n\n this.chatHistorySection.classList.remove('show');\n };\n }\n\n function initialize(app, config) {\n if (!app || app.widgetIsInitialized) {\n return;\n }\n\n if (!config.widget.chatWidgetContainer) {\n console.error('The widget chatWidgetContainer is required.');\n return;\n }\n\n if (!config.widget.chatWidgetStateName) {\n console.error('The widget chatWidgetStateName is required.');\n return;\n }\n\n var chatWidgetContainer = document.querySelector(config.widget.chatWidgetContainer);\n if (!chatWidgetContainer) {\n return;\n }\n\n if (config.widget.chatHistorySection) {\n app.chatHistorySection = document.querySelector(config.widget.chatHistorySection);\n }\n\n app.chatWidgetStateName = config.widget.chatWidgetStateName;\n app.chatWidgetStateSession = config.widget.chatWidgetStateName + 'Session';\n app.chatWidgetStateDocuments = config.widget.chatWidgetStateName + 'Documents';\n app.chatWidgetLayoutKey = config.widget.chatWidgetStateName + 'Layout';\n app.widgetContainerElement = chatWidgetContainer;\n app.widgetToggleButtonElement = config.widget.toggleButtonSelector ? document.querySelector(config.widget.toggleButtonSelector) : null;\n app.widgetResetSizeButtonElement = config.widget.resetSizeButtonSelector ? document.querySelector(config.widget.resetSizeButtonSelector) : null;\n app.widgetDefaultWidth = parsePixelValue(config.widget.defaultWidth) || parsePixelValue(window.getComputedStyle(chatWidgetContainer).width) || 380;\n app.widgetDefaultHeight = parsePixelValue(config.widget.defaultHeight) || parsePixelValue(window.getComputedStyle(chatWidgetContainer).height) || 520;\n app.widgetIsInitialized = true;\n app.clearStoredWidgetDocuments();\n app.documents = [];\n\n if (config.widget.enableResizing) {\n chatWidgetContainer.classList.add('ai-chat-widget-resizable');\n chatWidgetContainer.style.minWidth = (parsePixelValue(config.widget.minWidth) || 320) + 'px';\n chatWidgetContainer.style.minHeight = (parsePixelValue(config.widget.minHeight) || 420) + 'px';\n\n if (typeof ResizeObserver !== 'undefined') {\n app.widgetResizeObserver = new ResizeObserver(function () {\n app.persistWidgetPanelSize();\n app.constrainWidgetElementsToViewport();\n app.updateWidgetResetSizeButtonVisibility();\n });\n\n app.widgetResizeObserver.observe(chatWidgetContainer);\n }\n }\n\n var dragHandleSelector = config.widget.dragHandleSelector || '.ai-chat-widget-header';\n var dragHandle = chatWidgetContainer.querySelector(dragHandleSelector);\n\n if (config.widget.enableDragging && dragHandle) {\n dragHandle.classList.add('ai-chat-widget-drag-handle');\n chatWidgetContainer.classList.add('ai-chat-widget-draggable');\n app.attachDraggableWidgetElement(chatWidgetContainer, dragHandle, 'panel', false);\n }\n\n if (config.widget.enableDragging && app.widgetToggleButtonElement) {\n app.widgetToggleButtonElement.classList.add('ai-chat-widget-draggable');\n app.attachDraggableWidgetElement(app.widgetToggleButtonElement, app.widgetToggleButtonElement, 'toggle', true);\n }\n\n if (app.widgetResetSizeButtonElement) {\n app.widgetResetSizeButtonElement.addEventListener('click', function (event) {\n event.preventDefault();\n app.resetWidgetSize();\n });\n }\n\n app.restoreWidgetLayout();\n\n if (!app.widgetViewportResizeHandler) {\n app.widgetViewportResizeHandler = function () {\n if (config.widget.persistLayout) {\n app.restoreWidgetLayout();\n } else {\n app.constrainWidgetElementsToViewport();\n }\n\n app.updateWidgetResetSizeButtonVisibility();\n };\n\n window.addEventListener('resize', app.widgetViewportResizeHandler);\n }\n\n app.reloadCurrentSession();\n\n if (config.autoCreateSession && !app.getSessionId()) {\n app.startNewSession();\n }\n\n if (config.widget.showHistoryButton && app.chatHistorySection) {\n var showHistoryButton = document.querySelector(config.widget.showHistoryButton);\n if (showHistoryButton) {\n showHistoryButton.addEventListener('click', function () {\n app.chatHistorySection.classList.toggle('show');\n });\n }\n\n if (config.widget.closeHistoryButton) {\n var closeHistoryButton = document.querySelector(config.widget.closeHistoryButton);\n if (closeHistoryButton) {\n closeHistoryButton.addEventListener('click', function () {\n app.showChatScreen();\n });\n }\n }\n }\n\n if (config.widget.newChatButton) {\n var newChatButton = document.querySelector(config.widget.newChatButton);\n if (newChatButton) {\n newChatButton.addEventListener('click', function () {\n app.resetSession();\n app.showChatScreen();\n });\n }\n }\n }\n\n function resolveSessionId(app) {\n if (!app || !app.widgetIsInitialized) {\n return null;\n }\n\n return localStorage.getItem(app.chatWidgetStateSession);\n }\n\n function onSessionInitialized(app, sessionId) {\n if (app && app.widgetIsInitialized) {\n localStorage.setItem(app.chatWidgetStateSession, sessionId);\n }\n }\n\n function onSessionReset(app) {\n if (app && app.widgetIsInitialized) {\n localStorage.removeItem(app.chatWidgetStateSession);\n app.clearStoredWidgetDocuments();\n }\n }\n\n function onDocumentsChanged(app, documents) {\n if (app && app.widgetIsInitialized) {\n app.saveStoredWidgetDocuments(documents);\n }\n }\n\n function handleReceiveError(app) {\n if (app && app.widgetIsInitialized && !app.isSessionStarted && !app._attemptedSessionRecovery) {\n app._attemptedSessionRecovery = true;\n localStorage.removeItem(app.chatWidgetStateSession);\n app.clearStoredWidgetDocuments();\n app.startNewSession();\n }\n }\n\n function dispose(app) {\n if (!app) {\n return;\n }\n\n if (app.widgetResizeObserver) {\n app.widgetResizeObserver.disconnect();\n app.widgetResizeObserver = null;\n }\n\n if (app.widgetViewportResizeHandler) {\n window.removeEventListener('resize', app.widgetViewportResizeHandler);\n app.widgetViewportResizeHandler = null;\n }\n }\n\n return {\n attach: attach,\n initialize: initialize,\n onMounted: initialize,\n resolveSessionId: resolveSessionId,\n onSessionInitialized: onSessionInitialized,\n onSessionReset: onSessionReset,\n onDocumentsChanged: onDocumentsChanged,\n handleReceiveError: handleReceiveError,\n dispose: dispose,\n onBeforeUnmount: dispose\n };\n}();\n\nwindow.coreAIChatWidgetManager = window.coreAIChatWidgetManager || function () {\n function getAttributeValue(element, attributeName) {\n var value = element.getAttribute(attributeName);\n return value === null || value === '' ? null : value;\n }\n\n function parseBooleanAttributeValue(value) {\n if (value === null || value === undefined) {\n return null;\n }\n\n if (typeof value === 'boolean') {\n return value;\n }\n\n var normalized = String(value).trim().toLowerCase();\n if (normalized === 'true') {\n return true;\n }\n\n if (normalized === 'false') {\n return false;\n }\n\n return null;\n }\n\n function parseJsonAttribute(element, attributeName, description) {\n var rawValue = getAttributeValue(element, attributeName);\n if (!rawValue) {\n return null;\n }\n\n try {\n return JSON.parse(rawValue);\n }\n catch (error) {\n console.error('Failed to parse ' + description + ' JSON.', error);\n return null;\n }\n }\n\n function buildOptionsFromDataAttributes(element) {\n var widgetContainerSelector = getAttributeValue(element, 'data-coreai-chat-widget-container-selector');\n if (!widgetContainerSelector) {\n return null;\n }\n\n var chatConfig = null;\n if (window.coreAIChatManager && typeof window.coreAIChatManager.buildConfigFromElement === 'function') {\n chatConfig = window.coreAIChatManager.buildConfigFromElement(element, { allowWidgetHost: true });\n }\n\n var profileId = getAttributeValue(element, 'data-coreai-chat-widget-profile-id');\n var profileName = getAttributeValue(element, 'data-coreai-chat-widget-profile-name');\n var profileDisplayText = getAttributeValue(element, 'data-coreai-chat-widget-profile-display-text');\n var profileWelcomeMessage = getAttributeValue(element, 'data-coreai-chat-widget-profile-welcome-message');\n var profileChatMode = getAttributeValue(element, 'data-coreai-chat-widget-profile-chat-mode');\n var profileTtsVoiceName = getAttributeValue(element, 'data-coreai-chat-widget-profile-tts-voice-name');\n var profileMetricsEnabled = parseBooleanAttributeValue(getAttributeValue(element, 'data-coreai-chat-widget-profile-enable-session-metrics'));\n var profileSessionDocuments = parseBooleanAttributeValue(getAttributeValue(element, 'data-coreai-chat-widget-profile-allow-session-documents'));\n var profile = null;\n\n if (profileId || profileName || profileDisplayText || profileWelcomeMessage || profileChatMode || profileTtsVoiceName || profileMetricsEnabled !== null || profileSessionDocuments !== null) {\n profile = {\n id: profileId,\n name: profileName,\n displayText: profileDisplayText,\n welcomeMessage: profileWelcomeMessage,\n chatMode: profileChatMode,\n ttsVoiceName: profileTtsVoiceName,\n enableSessionMetrics: profileMetricsEnabled === true,\n allowSessionDocuments: profileSessionDocuments === true\n };\n }\n\n var enableDragging = parseBooleanAttributeValue(getAttributeValue(element, 'data-coreai-chat-widget-enable-dragging'));\n var enableResizing = parseBooleanAttributeValue(getAttributeValue(element, 'data-coreai-chat-widget-enable-resizing'));\n var persistLayout = parseBooleanAttributeValue(getAttributeValue(element, 'data-coreai-chat-widget-persist-layout'));\n\n return {\n shellSelector: getAttributeValue(element, 'data-coreai-chat-widget-shell-selector'),\n widgetContainerSelector: widgetContainerSelector,\n toggleButtonSelector: getAttributeValue(element, 'data-coreai-chat-widget-toggle-button-selector'),\n closeButtonSelector: getAttributeValue(element, 'data-coreai-chat-widget-close-button-selector'),\n inputSelector: getAttributeValue(element, 'data-coreai-chat-widget-input-selector'),\n messageTemplateSelector: getAttributeValue(element, 'data-coreai-chat-widget-message-template-selector'),\n indicatorTemplateSelector: getAttributeValue(element, 'data-coreai-chat-widget-indicator-template-selector'),\n profile: profile,\n widgetStateName: getAttributeValue(element, 'data-coreai-chat-widget-state-name'),\n openStateValue: getAttributeValue(element, 'data-coreai-chat-widget-open-state-value'),\n closedStateValue: getAttributeValue(element, 'data-coreai-chat-widget-closed-state-value'),\n openIconHtml: getAttributeValue(element, 'data-coreai-chat-widget-open-icon-html'),\n closedIconHtml: getAttributeValue(element, 'data-coreai-chat-widget-closed-icon-html'),\n chatConfig: chatConfig ? Object.assign({}, chatConfig, {\n widget: Object.assign({}, chatConfig.widget || {}, {\n chatWidgetContainer: widgetContainerSelector,\n chatWidgetStateName: getAttributeValue(element, 'data-coreai-chat-widget-state-name'),\n newChatButton: getAttributeValue(element, 'data-coreai-chat-widget-new-chat-button-selector'),\n toggleButtonSelector: getAttributeValue(element, 'data-coreai-chat-widget-toggle-button-selector'),\n resetSizeButtonSelector: getAttributeValue(element, 'data-coreai-chat-widget-reset-size-button-selector'),\n dragHandleSelector: getAttributeValue(element, 'data-coreai-chat-widget-drag-handle-selector'),\n enableDragging: enableDragging === null ? undefined : enableDragging,\n enableResizing: enableResizing === null ? undefined : enableResizing,\n persistLayout: persistLayout === null ? undefined : persistLayout,\n })\n }) : null\n };\n }\n\n function initialize(options) {\n if (!options) {\n return null;\n }\n\n var chatConfig = options.chatConfig;\n if (!chatConfig && options.configElementSelector) {\n var configElement = document.querySelector(options.configElementSelector);\n chatConfig = configElement ? parseJsonAttribute(configElement, 'data-config', 'AI chat widget config') : null;\n }\n\n if (!chatConfig) {\n return null;\n }\n\n if (options.messageTemplateSelector) {\n var messageTemplate = document.querySelector(options.messageTemplateSelector);\n if (messageTemplate) {\n chatConfig.messageTemplate = messageTemplate.innerHTML;\n }\n }\n\n if (options.indicatorTemplateSelector) {\n var indicatorTemplate = document.querySelector(options.indicatorTemplateSelector);\n if (indicatorTemplate) {\n chatConfig.indicatorTemplate = indicatorTemplate.innerHTML;\n }\n }\n\n var shell = document.querySelector(options.shellSelector);\n var widgetContainer = document.querySelector(options.widgetContainerSelector);\n var toggleButton = document.querySelector(options.toggleButtonSelector);\n var closeButton = document.querySelector(options.closeButtonSelector);\n var profileInput = options.inputSelector ? document.querySelector(options.inputSelector) : null;\n var widgetStateName = options.widgetStateName || chatConfig.widget.chatWidgetStateName;\n var widgetOpenStateKey = options.widgetOpenStateKey || (widgetStateName + 'Open');\n var widgetLayoutKey = widgetStateName + 'Layout';\n var openStateValue = options.openStateValue || 'open';\n var closedStateValue = options.closedStateValue || 'closed';\n\n if (profileInput && options.profile && options.profile.id) {\n profileInput.setAttribute('data-profile-id', options.profile.id);\n }\n\n try {\n var storedLayout = localStorage.getItem(widgetLayoutKey);\n var layout = storedLayout ? JSON.parse(storedLayout) || {} : {};\n var position = layout.position || {};\n var panelLayout = layout.panel || {};\n var toggleLeft = Number(position.left);\n var toggleTop = Number(position.top);\n var isOpen = localStorage.getItem(widgetOpenStateKey) === openStateValue;\n var viewportPadding = 8;\n\n if (shell) {\n shell.dataset.deferReveal = isOpen ? 'true' : 'false';\n shell.dataset.initialOpen = isOpen ? 'true' : 'false';\n }\n\n if (widgetContainer && toggleButton) {\n var toggleSize = 52;\n var panelWidth = Number.isFinite(Number(panelLayout.width))\n ? Number(panelLayout.width)\n : Math.round(parseFloat(window.getComputedStyle(widgetContainer).width) || 380);\n var panelHeight = Number.isFinite(Number(panelLayout.height))\n ? Number(panelLayout.height)\n : Math.round(parseFloat(window.getComputedStyle(widgetContainer).height) || 520);\n var maxLeft = Math.max(viewportPadding, window.innerWidth - toggleSize - viewportPadding);\n var maxTop = Math.max(viewportPadding, window.innerHeight - toggleSize - viewportPadding);\n if (Number.isFinite(Number(position.leftRatio))) {\n toggleLeft = viewportPadding + Math.max(0, maxLeft - viewportPadding) * Number(position.leftRatio);\n }\n if (Number.isFinite(Number(position.topRatio))) {\n toggleTop = viewportPadding + Math.max(0, maxTop - viewportPadding) * Number(position.topRatio);\n }\n if (Number.isFinite(toggleLeft) && Number.isFinite(toggleTop)) {\n toggleLeft = Math.round(clampWidgetValue(toggleLeft, viewportPadding, maxLeft));\n toggleTop = Math.round(clampWidgetValue(toggleTop, viewportPadding, maxTop));\n }\n\n if (Number.isFinite(toggleLeft) && Number.isFinite(toggleTop)) {\n toggleButton.style.left = toggleLeft + 'px';\n toggleButton.style.top = toggleTop + 'px';\n toggleButton.style.right = 'auto';\n toggleButton.style.bottom = 'auto';\n\n var toggleGap = 8;\n widgetContainer.style.left = (toggleLeft + toggleSize - panelWidth) + 'px';\n widgetContainer.style.top = (toggleTop - panelHeight - toggleGap) + 'px';\n widgetContainer.style.right = 'auto';\n widgetContainer.style.bottom = 'auto';\n }\n }\n\n if (widgetContainer) {\n widgetContainer.classList.remove('open');\n widgetContainer.style.display = 'none';\n widgetContainer.setAttribute('aria-hidden', 'true');\n }\n\n if (toggleButton) {\n toggleButton.innerHTML = isOpen ? options.openIconHtml : options.closedIconHtml;\n }\n }\n catch (error) {\n console.warn('Failed to restore widget layout before initialization.', error);\n }\n finally {\n if (shell && shell.dataset.deferReveal !== 'true') {\n shell.style.visibility = '';\n }\n }\n\n var widgetApp = window.coreAIChatManager.initialize(chatConfig);\n if (options.applySessionProfilePatch !== false && window.crestAppsAIChat && window.crestAppsAIChat.patchSessionProfileSync) {\n window.crestAppsAIChat.patchSessionProfileSync(widgetApp);\n }\n\n function revealShell() {\n if (!shell) {\n return;\n }\n\n shell.style.visibility = '';\n shell.dataset.deferReveal = 'false';\n }\n\n function syncOpenPanelPosition() {\n if (!widgetApp || typeof widgetApp.syncPanelPositionToToggle !== 'function') {\n return;\n }\n\n widgetApp.syncPanelPositionToToggle(false);\n }\n\n function updateTtsPlaybackButtons() {\n if (!widgetContainer) {\n return;\n }\n\n var buttons = widgetContainer.querySelectorAll('[data-tts-message-index]');\n buttons.forEach(function (button) {\n var buttonIndex = Number(button.getAttribute('data-tts-message-index'));\n var isPlaying = buttonIndex === widgetApp.ttsPlayingMessageIndex;\n button.classList.toggle('tts-playing', isPlaying);\n button.setAttribute('title', isPlaying ? 'Pause audio' : 'Read aloud');\n });\n }\n\n function queueTtsPlaybackButtonUpdate() {\n requestAnimationFrame(updateTtsPlaybackButtons);\n }\n\n function revealShellWhenStable(initialOpen) {\n if (!shell || shell.dataset.deferReveal !== 'true' || !initialOpen) {\n revealShell();\n return;\n }\n\n var hasRevealed = false;\n var resizeObserver = null;\n\n function finalizeReveal() {\n if (hasRevealed) {\n return;\n }\n\n hasRevealed = true;\n\n if (resizeObserver) {\n resizeObserver.disconnect();\n }\n\n requestAnimationFrame(function () {\n syncOpenPanelPosition();\n requestAnimationFrame(function () {\n revealShell();\n });\n });\n }\n\n if (typeof ResizeObserver === 'undefined') {\n window.setTimeout(finalizeReveal, 0);\n return;\n }\n\n var lastWidth = 0;\n var lastHeight = 0;\n var stablePasses = 0;\n\n resizeObserver = new ResizeObserver(function (entries) {\n var entry = entries && entries[0];\n if (!entry) {\n return;\n }\n\n var width = Math.round(entry.contentRect.width);\n var height = Math.round(entry.contentRect.height);\n if (!width || !height) {\n return;\n }\n\n syncOpenPanelPosition();\n\n if (width === lastWidth && height === lastHeight) {\n stablePasses++;\n }\n else {\n lastWidth = width;\n lastHeight = height;\n stablePasses = 0;\n }\n\n if (stablePasses >= 1) {\n finalizeReveal();\n }\n });\n\n resizeObserver.observe(widgetContainer);\n window.setTimeout(finalizeReveal, 150);\n }\n\n function setWidgetOpen(isOpen) {\n if (widgetApp) {\n var isCurrentlyOpen = widgetContainer.classList.contains('open');\n if (isOpen && !isCurrentlyOpen && typeof widgetApp.syncPanelPositionToToggle === 'function') {\n widgetApp.syncPanelPositionToToggle();\n }\n else if (!isOpen && isCurrentlyOpen && typeof widgetApp.syncTogglePositionToPanel === 'function') {\n widgetApp.syncTogglePositionToPanel();\n }\n }\n\n widgetContainer.classList.toggle('open', isOpen);\n widgetContainer.style.display = isOpen ? 'flex' : 'none';\n widgetContainer.setAttribute('aria-hidden', isOpen ? 'false' : 'true');\n toggleButton.innerHTML = isOpen ? options.openIconHtml : options.closedIconHtml;\n localStorage.setItem(widgetOpenStateKey, isOpen ? openStateValue : closedStateValue);\n\n if (isOpen && typeof window.renderPendingCharts === 'function') {\n setTimeout(function () { window.renderPendingCharts(); }, 100);\n }\n }\n\n var initialOpen = shell && shell.dataset.initialOpen === 'true';\n setWidgetOpen(initialOpen);\n revealShellWhenStable(initialOpen);\n\n if (widgetApp && typeof widgetApp.$watch === 'function') {\n widgetApp.$watch('ttsPlayingMessageIndex', function () {\n queueTtsPlaybackButtonUpdate();\n });\n }\n\n queueTtsPlaybackButtonUpdate();\n\n if (toggleButton) {\n toggleButton.addEventListener('click', function () {\n if (toggleButton.dataset.dragSuppressClick === 'true') {\n toggleButton.dataset.dragSuppressClick = 'false';\n return;\n }\n\n setWidgetOpen(!widgetContainer.classList.contains('open'));\n });\n }\n\n if (closeButton) {\n closeButton.addEventListener('click', function () {\n setWidgetOpen(false);\n });\n }\n\n return widgetApp;\n }\n\n function initializeFromElement(element) {\n if (!element || element.dataset.coreAiChatWidgetInitialized === 'true') {\n return element ? element.__coreAIChatWidgetApp || null : null;\n }\n\n var jsonOptions = parseJsonAttribute(element, 'data-coreai-chat-widget-config', 'CoreAI chat widget config');\n var attributeOptions = buildOptionsFromDataAttributes(element);\n if (!jsonOptions && !attributeOptions) {\n return null;\n }\n\n var options = Object.assign({}, jsonOptions || {}, attributeOptions || {});\n\n var widgetApp = initialize(options);\n if (!widgetApp) {\n return null;\n }\n\n element.dataset.coreAiChatWidgetInitialized = 'true';\n element.__coreAIChatWidgetApp = widgetApp;\n\n return widgetApp;\n }\n\n function scanForAutoInitialization(root) {\n if (!root || typeof root.querySelectorAll !== 'function') {\n return;\n }\n\n if (typeof root.matches === 'function' && root.matches('[data-coreai-chat-widget-config],[data-coreai-chat-widget-container-selector]')) {\n initializeFromElement(root);\n }\n\n root.querySelectorAll('[data-coreai-chat-widget-config],[data-coreai-chat-widget-container-selector]').forEach(initializeFromElement);\n }\n\n function startAutoInitialization() {\n scanForAutoInitialization(document);\n\n if (typeof MutationObserver === 'undefined') {\n return;\n }\n\n var observer = new MutationObserver(function (mutations) {\n mutations.forEach(function (mutation) {\n mutation.addedNodes.forEach(function (node) {\n if (node && node.nodeType === 1) {\n scanForAutoInitialization(node);\n }\n });\n });\n });\n\n observer.observe(document.body, {\n childList: true,\n subtree: true,\n });\n }\n\n if (document.readyState === 'loading') {\n document.addEventListener('DOMContentLoaded', startAutoInitialization, { once: true });\n } else {\n startAutoInitialization();\n }\n\n return {\n initialize: initialize,\n initializeFromElement: initializeFromElement,\n };\n}();\n"]} +{"version":3,"sources":["ai-chat-widget.js"],"names":["clampWidgetValue","value","min","max","Math","window","coreAIChatWidgetBehavior","parsePixelValue","Number","isFinite","parsed","parseFloat","attach","app","config","__aiChatWidgetAttached","chatWidgetStateName","chatWidgetStateSession","chatWidgetStateDocuments","chatWidgetLayoutKey","chatHistorySection","widgetContainerElement","widgetToggleButtonElement","widgetResetSizeButtonElement","widgetResizeObserver","widgetViewportResizeHandler","widgetDefaultWidth","widgetDefaultHeight","widgetIsInitialized","getStoredWidgetLayout","widget","persistLayout","storedLayout","localStorage","getItem","JSON","parse","error","console","warn","saveStoredWidgetLayout","partialLayout","currentLayout","nextLayout","Object","assign","panel","undefined","position","setItem","stringify","getElementSize","element","fallbackWidth","fallbackHeight","width","height","rect","getBoundingClientRect","computed","getComputedStyle","round","getElementPosition","left","top","inlineLeft","style","inlineTop","computedLeft","computedTop","isHidden","display","getAvailableWidgetPositionRange","viewportPadding","padding","maxLeft","innerWidth","maxTop","innerHeight","createStoredPosition","range","leftSpan","topSpan","leftRatio","topRatio","resolveStoredPosition","storedPosition","clampWidgetPosition","getStoredWidgetDocuments","clearStoredWidgetDocuments","saveStoredWidgetDocuments","removeItem","applyAbsolutePosition","right","bottom","getWidgetDefaultSize","defaultWidth","defaultHeight","getWidgetToggleGap","isWidgetPanelVisible","classList","contains","persistWidgetPanelPosition","panelDefaultSize","panelPosition","panelSize","toggleSize","linkedPosition","persistWidgetTogglePosition","togglePosition","persistWidgetPanelSize","enableResizing","defaultSize","currentSize","abs","syncTogglePositionToPanel","syncPanelPositionToToggle","updateWidgetResetSizeButtonVisibility","add","isResized","toggle","resetWidgetSize","removeProperty","constrainWidgetElementsToViewport","restoreWidgetLayout","storedTogglePosition","enableDragging","attachDraggableWidgetElement","handle","layoutKey","suppressClickOnDrag","activePointerId","startX","startY","startLeft","startTop","dragged","dragThreshold","interactiveSelector","self","stopDragging","event","pointerId","document","removeEventListener","onPointerMove","remove","dataset","dragSuppressClick","setTimeout","deltaX","clientX","deltaY","clientY","hypot","nextPosition","addEventListener","button","target","closest","setPointerCapture","preventDefault","clampedPanel","clampedToggle","showChatScreen","initialize","chatWidgetContainer","querySelector","toggleButtonSelector","resetSizeButtonSelector","documents","minWidth","minHeight","ResizeObserver","observe","dragHandleSelector","dragHandle","reloadCurrentSession","showHistoryButton","closeHistoryButton","newChatButton","resetSession","resolveSessionId","onSessionInitialized","sessionId","onSessionReset","onDocumentsChanged","handleReceiveError","isSessionStarted","_attemptedSessionRecovery","startNewSession","dispose","disconnect","onMounted","onBeforeUnmount","coreAIChatWidgetManager","getAttributeValue","attributeName","getAttribute","parseBooleanAttributeValue","normalized","String","trim","toLowerCase","parseJsonAttribute","description","rawValue","buildOptionsFromDataAttributes","widgetContainerSelector","chatConfig","coreAIChatManager","buildConfigFromElement","allowWidgetHost","profileId","profileName","profileDisplayText","profileWelcomeMessage","profileChatMode","profileTtsVoiceName","profileMetricsEnabled","profileSessionDocuments","profile","id","name","displayText","welcomeMessage","chatMode","ttsVoiceName","enableSessionMetrics","allowSessionDocuments","shellSelector","closeButtonSelector","inputSelector","messageTemplateSelector","indicatorTemplateSelector","widgetStateName","openStateValue","closedStateValue","openIconHtml","closedIconHtml","options","configElementSelector","configElement","messageTemplate","innerHTML","indicatorTemplate","shell","widgetContainer","toggleButton","closeButton","profileInput","widgetOpenStateKey","widgetLayoutKey","setAttribute","layout","panelLayout","toggleLeft","toggleTop","isOpen","deferReveal","initialOpen","panelWidth","panelHeight","toggleGap","visibility","widgetApp","applySessionProfilePatch","crestAppsAIChat","patchSessionProfileSync","revealShell","syncOpenPanelPosition","updateTtsPlaybackButtons","buttons","querySelectorAll","forEach","buttonIndex","isPlaying","ttsPlayingMessageIndex","queueTtsPlaybackButtonUpdate","requestAnimationFrame","revealShellWhenStable","hasRevealed","resizeObserver","finalizeReveal","lastWidth","lastHeight","stablePasses","entries","entry","contentRect","setWidgetOpen","isCurrentlyOpen","renderPendingCharts","$watch","initializeFromElement","coreAiChatWidgetInitialized","__coreAIChatWidgetApp","jsonOptions","attributeOptions","scanForAutoInitialization","root","matches","startAutoInitialization","MutationObserver","observer","mutations","mutation","addedNodes","node","nodeType","body","childList","subtree","readyState","once"],"mappings":"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","file":"ai-chat-widget.js","sourcesContent":["function clampWidgetValue(value, min, max) {\n return Math.min(Math.max(value, min), max);\n}\n\nwindow.coreAIChatWidgetBehavior = window.coreAIChatWidgetBehavior || function () {\n function parsePixelValue(value) {\n if (typeof value === 'number' && Number.isFinite(value)) {\n return value;\n }\n\n if (typeof value !== 'string') {\n return null;\n }\n\n var parsed = parseFloat(value);\n return Number.isFinite(parsed) ? parsed : null;\n }\n\n function attach(app, config) {\n if (!app || app.__aiChatWidgetAttached) {\n return;\n }\n\n app.__aiChatWidgetAttached = true;\n app.chatWidgetStateName = null;\n app.chatWidgetStateSession = null;\n app.chatWidgetStateDocuments = null;\n app.chatWidgetLayoutKey = null;\n app.chatHistorySection = null;\n app.widgetContainerElement = null;\n app.widgetToggleButtonElement = null;\n app.widgetResetSizeButtonElement = null;\n app.widgetResizeObserver = null;\n app.widgetViewportResizeHandler = null;\n app.widgetDefaultWidth = null;\n app.widgetDefaultHeight = null;\n app.widgetIsInitialized = false;\n\n app.getStoredWidgetLayout = function () {\n if (!this.chatWidgetLayoutKey || !config.widget.persistLayout) {\n return {};\n }\n\n try {\n var storedLayout = localStorage.getItem(this.chatWidgetLayoutKey);\n return storedLayout ? JSON.parse(storedLayout) || {} : {};\n }\n catch (error) {\n console.warn('Failed to read widget layout state.', error);\n return {};\n }\n };\n\n app.saveStoredWidgetLayout = function (partialLayout) {\n if (!this.chatWidgetLayoutKey || !config.widget.persistLayout) {\n return;\n }\n\n var currentLayout = this.getStoredWidgetLayout();\n var nextLayout = Object.assign({}, currentLayout);\n\n if (partialLayout.panel !== undefined) {\n nextLayout.panel = Object.assign({}, currentLayout.panel || {}, partialLayout.panel || {});\n }\n\n if (partialLayout.position !== undefined) {\n nextLayout.position = Object.assign({}, currentLayout.position || {}, partialLayout.position || {});\n }\n\n localStorage.setItem(this.chatWidgetLayoutKey, JSON.stringify(nextLayout));\n };\n\n app.getElementSize = function (element, fallbackWidth, fallbackHeight) {\n if (!element) {\n return {\n width: fallbackWidth || 0,\n height: fallbackHeight || 0\n };\n }\n\n var rect = element.getBoundingClientRect();\n var computed = window.getComputedStyle(element);\n\n return {\n width: Math.round(rect.width || parsePixelValue(computed.width) || fallbackWidth || 0),\n height: Math.round(rect.height || parsePixelValue(computed.height) || fallbackHeight || 0)\n };\n };\n\n app.getElementPosition = function (element) {\n if (!element) {\n return {\n left: 0,\n top: 0\n };\n }\n\n var rect = element.getBoundingClientRect();\n var computed = window.getComputedStyle(element);\n var inlineLeft = parsePixelValue(element.style.left);\n var inlineTop = parsePixelValue(element.style.top);\n var computedLeft = parsePixelValue(computed.left);\n var computedTop = parsePixelValue(computed.top);\n var isHidden = computed.display === 'none';\n\n return {\n left: Math.round(isHidden && Number.isFinite(inlineLeft) ? inlineLeft : rect.left || inlineLeft || computedLeft || 0),\n top: Math.round(isHidden && Number.isFinite(inlineTop) ? inlineTop : rect.top || inlineTop || computedTop || 0)\n };\n };\n\n app.getAvailableWidgetPositionRange = function (width, height) {\n var viewportPadding = 8;\n return {\n padding: viewportPadding,\n maxLeft: Math.max(viewportPadding, window.innerWidth - width - viewportPadding),\n maxTop: Math.max(viewportPadding, window.innerHeight - height - viewportPadding)\n };\n };\n\n app.createStoredPosition = function (left, top, width, height) {\n var range = this.getAvailableWidgetPositionRange(width, height);\n var leftSpan = Math.max(0, range.maxLeft - range.padding);\n var topSpan = Math.max(0, range.maxTop - range.padding);\n\n return {\n left: Math.round(left),\n top: Math.round(top),\n leftRatio: leftSpan === 0 ? 0 : (left - range.padding) / leftSpan,\n topRatio: topSpan === 0 ? 0 : (top - range.padding) / topSpan\n };\n };\n\n app.resolveStoredPosition = function (storedPosition, width, height) {\n if (!storedPosition) {\n return null;\n }\n\n var range = this.getAvailableWidgetPositionRange(width, height);\n var left = Number(storedPosition.left);\n var top = Number(storedPosition.top);\n var leftRatio = Number(storedPosition.leftRatio);\n var topRatio = Number(storedPosition.topRatio);\n\n if (Number.isFinite(leftRatio)) {\n left = range.padding + Math.max(0, range.maxLeft - range.padding) * leftRatio;\n }\n\n if (Number.isFinite(topRatio)) {\n top = range.padding + Math.max(0, range.maxTop - range.padding) * topRatio;\n }\n\n if (!Number.isFinite(left) || !Number.isFinite(top)) {\n return null;\n }\n\n return this.clampWidgetPosition(left, top, width, height);\n };\n\n app.clampWidgetPosition = function (left, top, width, height) {\n var range = this.getAvailableWidgetPositionRange(width, height);\n\n return {\n left: Math.round(clampWidgetValue(left, range.padding, range.maxLeft)),\n top: Math.round(clampWidgetValue(top, range.padding, range.maxTop))\n };\n };\n\n app.getStoredWidgetDocuments = function () {\n this.clearStoredWidgetDocuments();\n return [];\n };\n\n app.saveStoredWidgetDocuments = function () {\n this.clearStoredWidgetDocuments();\n };\n\n app.clearStoredWidgetDocuments = function () {\n if (!this.chatWidgetStateDocuments) {\n return;\n }\n\n localStorage.removeItem(this.chatWidgetStateDocuments);\n };\n\n app.applyAbsolutePosition = function (element, left, top) {\n if (!element) {\n return;\n }\n\n element.style.left = left + 'px';\n element.style.top = top + 'px';\n element.style.right = 'auto';\n element.style.bottom = 'auto';\n };\n\n app.getWidgetDefaultSize = function () {\n return {\n width: this.widgetDefaultWidth || parsePixelValue(config.widget.defaultWidth) || 380,\n height: this.widgetDefaultHeight || parsePixelValue(config.widget.defaultHeight) || 520\n };\n };\n\n app.getWidgetToggleGap = function () {\n return 8;\n };\n\n app.isWidgetPanelVisible = function () {\n if (!this.widgetContainerElement) {\n return false;\n }\n\n var computed = window.getComputedStyle(this.widgetContainerElement);\n return this.widgetContainerElement.classList.contains('open') && computed.display !== 'none';\n };\n\n app.persistWidgetPanelPosition = function () {\n if (!this.widgetContainerElement || !config.widget.persistLayout) {\n return;\n }\n\n var panelDefaultSize = this.getWidgetDefaultSize();\n var panelPosition = this.getElementPosition(this.widgetContainerElement);\n var panelSize = this.getElementSize(this.widgetContainerElement, panelDefaultSize.width, panelDefaultSize.height);\n var toggleSize = this.getElementSize(this.widgetToggleButtonElement, 52, 52);\n var linkedPosition = this.clampWidgetPosition(\n panelPosition.left + panelSize.width - toggleSize.width,\n panelPosition.top + panelSize.height + this.getWidgetToggleGap(),\n toggleSize.width,\n toggleSize.height);\n\n this.saveStoredWidgetLayout({ position: this.createStoredPosition(linkedPosition.left, linkedPosition.top, toggleSize.width, toggleSize.height) });\n };\n\n app.persistWidgetTogglePosition = function () {\n if (!this.widgetToggleButtonElement || !config.widget.persistLayout) {\n return;\n }\n\n var togglePosition = this.getElementPosition(this.widgetToggleButtonElement);\n var toggleSize = this.getElementSize(this.widgetToggleButtonElement, 52, 52);\n this.saveStoredWidgetLayout({ position: this.createStoredPosition(togglePosition.left, togglePosition.top, toggleSize.width, toggleSize.height) });\n };\n\n app.persistWidgetPanelSize = function () {\n if (!this.widgetContainerElement || !config.widget.enableResizing || !config.widget.persistLayout) {\n return;\n }\n\n var defaultSize = this.getWidgetDefaultSize();\n var currentSize = this.getElementSize(this.widgetContainerElement, defaultSize.width, defaultSize.height);\n\n this.saveStoredWidgetLayout({\n panel: {\n width: Math.abs(currentSize.width - defaultSize.width) <= 1 ? null : currentSize.width,\n height: Math.abs(currentSize.height - defaultSize.height) <= 1 ? null : currentSize.height\n }\n });\n };\n\n app.syncTogglePositionToPanel = function (persistLayout) {\n if (persistLayout === undefined) {\n persistLayout = true;\n }\n\n if (!this.widgetContainerElement || !this.widgetToggleButtonElement) {\n return;\n }\n\n var panelDefaultSize = this.getWidgetDefaultSize();\n var panelSize = this.getElementSize(this.widgetContainerElement, panelDefaultSize.width, panelDefaultSize.height);\n var toggleSize = this.getElementSize(this.widgetToggleButtonElement, 52, 52);\n var panelPosition = this.getElementPosition(this.widgetContainerElement);\n var linkedPosition = this.clampWidgetPosition(\n panelPosition.left + panelSize.width - toggleSize.width,\n panelPosition.top + panelSize.height + this.getWidgetToggleGap(),\n toggleSize.width,\n toggleSize.height);\n\n this.applyAbsolutePosition(this.widgetToggleButtonElement, linkedPosition.left, linkedPosition.top);\n\n if (persistLayout && config.widget.persistLayout) {\n this.persistWidgetTogglePosition();\n }\n };\n\n app.syncPanelPositionToToggle = function (persistLayout) {\n if (persistLayout === undefined) {\n persistLayout = true;\n }\n\n if (!this.widgetContainerElement || !this.widgetToggleButtonElement) {\n return;\n }\n\n var panelDefaultSize = this.getWidgetDefaultSize();\n var panelSize = this.getElementSize(this.widgetContainerElement, panelDefaultSize.width, panelDefaultSize.height);\n var toggleSize = this.getElementSize(this.widgetToggleButtonElement, 52, 52);\n var togglePosition = this.getElementPosition(this.widgetToggleButtonElement);\n var linkedPosition = this.clampWidgetPosition(\n togglePosition.left + toggleSize.width - panelSize.width,\n togglePosition.top - panelSize.height - this.getWidgetToggleGap(),\n panelSize.width,\n panelSize.height);\n\n this.applyAbsolutePosition(this.widgetContainerElement, linkedPosition.left, linkedPosition.top);\n\n if (persistLayout && config.widget.persistLayout) {\n this.persistWidgetPanelPosition();\n }\n };\n\n app.updateWidgetResetSizeButtonVisibility = function () {\n if (!this.widgetResetSizeButtonElement) {\n return;\n }\n\n if (!config.widget.enableResizing || !this.widgetContainerElement) {\n this.widgetResetSizeButtonElement.classList.add('d-none');\n return;\n }\n\n var defaultSize = this.getWidgetDefaultSize();\n var currentSize = this.getElementSize(this.widgetContainerElement, defaultSize.width, defaultSize.height);\n var isResized =\n Math.abs(currentSize.width - defaultSize.width) > 1 ||\n Math.abs(currentSize.height - defaultSize.height) > 1 ||\n !!this.widgetContainerElement.style.width ||\n !!this.widgetContainerElement.style.height;\n\n this.widgetResetSizeButtonElement.classList.toggle('d-none', !isResized);\n };\n\n app.resetWidgetSize = function () {\n if (!this.widgetContainerElement || !config.widget.enableResizing) {\n return;\n }\n\n this.widgetContainerElement.style.removeProperty('width');\n this.widgetContainerElement.style.removeProperty('height');\n this.persistWidgetPanelSize();\n this.constrainWidgetElementsToViewport();\n this.updateWidgetResetSizeButtonVisibility();\n };\n\n app.restoreWidgetLayout = function () {\n var storedLayout = this.getStoredWidgetLayout();\n\n if (this.widgetContainerElement && config.widget.enableResizing) {\n if (Number.isFinite(storedLayout.panel && storedLayout.panel.width)) {\n this.widgetContainerElement.style.width = storedLayout.panel.width + 'px';\n }\n else {\n this.widgetContainerElement.style.removeProperty('width');\n }\n\n if (Number.isFinite(storedLayout.panel && storedLayout.panel.height)) {\n this.widgetContainerElement.style.height = storedLayout.panel.height + 'px';\n }\n else {\n this.widgetContainerElement.style.removeProperty('height');\n }\n }\n\n var toggleSize = this.getElementSize(this.widgetToggleButtonElement, 52, 52);\n var storedTogglePosition = this.resolveStoredPosition(storedLayout.position, toggleSize.width, toggleSize.height);\n if (this.widgetToggleButtonElement && config.widget.enableDragging && storedTogglePosition) {\n this.applyAbsolutePosition(this.widgetToggleButtonElement, storedTogglePosition.left, storedTogglePosition.top);\n this.syncPanelPositionToToggle(false);\n }\n else if (this.widgetToggleButtonElement && config.widget.enableDragging &&\n Number.isFinite(storedLayout.toggle && storedLayout.toggle.left) &&\n Number.isFinite(storedLayout.toggle && storedLayout.toggle.top)) {\n this.applyAbsolutePosition(this.widgetToggleButtonElement, storedLayout.toggle.left, storedLayout.toggle.top);\n this.syncPanelPositionToToggle(false);\n }\n else if (this.widgetContainerElement && config.widget.enableDragging &&\n Number.isFinite(storedLayout.panel && storedLayout.panel.left) &&\n Number.isFinite(storedLayout.panel && storedLayout.panel.top)) {\n this.applyAbsolutePosition(this.widgetContainerElement, storedLayout.panel.left, storedLayout.panel.top);\n this.syncTogglePositionToPanel(false);\n }\n\n this.constrainWidgetElementsToViewport();\n this.updateWidgetResetSizeButtonVisibility();\n };\n\n app.attachDraggableWidgetElement = function (element, handle, layoutKey, suppressClickOnDrag) {\n if (!element || !handle || !config.widget.enableDragging) {\n return;\n }\n\n var activePointerId = null;\n var startX = 0;\n var startY = 0;\n var startLeft = 0;\n var startTop = 0;\n var dragged = false;\n var dragThreshold = 4;\n var interactiveSelector = 'button, a, input, textarea, select, option, label';\n var self = this;\n\n function stopDragging(event) {\n if (activePointerId === null) {\n return;\n }\n\n if (event && event.pointerId !== undefined && event.pointerId !== activePointerId) {\n return;\n }\n\n document.removeEventListener('pointermove', onPointerMove);\n document.removeEventListener('pointerup', stopDragging);\n document.removeEventListener('pointercancel', stopDragging);\n element.classList.remove('ai-chat-widget-dragging');\n activePointerId = null;\n\n if (!dragged) {\n return;\n }\n\n if (layoutKey === 'panel') {\n self.syncTogglePositionToPanel(false);\n self.persistWidgetPanelPosition();\n }\n else if (layoutKey === 'toggle') {\n self.syncPanelPositionToToggle(false);\n self.persistWidgetTogglePosition();\n }\n\n if (config.widget.persistLayout) {\n self.persistWidgetPanelPosition();\n self.persistWidgetTogglePosition();\n }\n\n if (suppressClickOnDrag) {\n element.dataset.dragSuppressClick = 'true';\n window.setTimeout(function () {\n if (element.dataset.dragSuppressClick === 'true') {\n element.dataset.dragSuppressClick = 'false';\n }\n }, 0);\n }\n }\n\n function onPointerMove(event) {\n if (activePointerId === null || event.pointerId !== activePointerId) {\n return;\n }\n\n var deltaX = event.clientX - startX;\n var deltaY = event.clientY - startY;\n\n if (!dragged && Math.hypot(deltaX, deltaY) < dragThreshold) {\n return;\n }\n\n dragged = true;\n\n var defaultSize = self.getWidgetDefaultSize();\n var currentSize = self.getElementSize(\n element,\n layoutKey === 'panel' ? defaultSize.width : 52,\n layoutKey === 'panel' ? defaultSize.height : 52);\n var nextPosition = self.clampWidgetPosition(startLeft + deltaX, startTop + deltaY, currentSize.width, currentSize.height);\n\n self.applyAbsolutePosition(element, nextPosition.left, nextPosition.top);\n\n if (layoutKey === 'panel') {\n self.syncTogglePositionToPanel(false);\n }\n else if (layoutKey === 'toggle') {\n self.syncPanelPositionToToggle(false);\n }\n }\n\n handle.addEventListener('pointerdown', function (event) {\n if (event.button !== 0) {\n return;\n }\n\n if (layoutKey === 'panel' && event.target.closest(interactiveSelector)) {\n return;\n }\n\n var rect = element.getBoundingClientRect();\n startX = event.clientX;\n startY = event.clientY;\n startLeft = rect.left;\n startTop = rect.top;\n dragged = false;\n activePointerId = event.pointerId;\n element.classList.add('ai-chat-widget-dragging');\n\n if (handle.setPointerCapture) {\n handle.setPointerCapture(event.pointerId);\n }\n\n document.addEventListener('pointermove', onPointerMove);\n document.addEventListener('pointerup', stopDragging);\n document.addEventListener('pointercancel', stopDragging);\n event.preventDefault();\n });\n };\n\n app.constrainWidgetElementsToViewport = function () {\n if (this.widgetContainerElement && this.widgetContainerElement.style.left && this.isWidgetPanelVisible()) {\n var panelDefaultSize = this.getWidgetDefaultSize();\n var panelSize = this.getElementSize(this.widgetContainerElement, panelDefaultSize.width, panelDefaultSize.height);\n var panelPosition = this.getElementPosition(this.widgetContainerElement);\n var clampedPanel = this.clampWidgetPosition(panelPosition.left, panelPosition.top, panelSize.width, panelSize.height);\n\n this.applyAbsolutePosition(this.widgetContainerElement, clampedPanel.left, clampedPanel.top);\n this.syncTogglePositionToPanel(false);\n\n if (config.widget.persistLayout) {\n this.persistWidgetPanelPosition();\n this.persistWidgetTogglePosition();\n }\n }\n else if (this.widgetToggleButtonElement && this.widgetToggleButtonElement.style.left) {\n var toggleSize = this.getElementSize(this.widgetToggleButtonElement, 52, 52);\n var togglePosition = this.getElementPosition(this.widgetToggleButtonElement);\n var clampedToggle = this.clampWidgetPosition(togglePosition.left, togglePosition.top, toggleSize.width, toggleSize.height);\n\n this.applyAbsolutePosition(this.widgetToggleButtonElement, clampedToggle.left, clampedToggle.top);\n this.syncPanelPositionToToggle(false);\n\n if (config.widget.persistLayout) {\n this.persistWidgetTogglePosition();\n this.persistWidgetPanelPosition();\n }\n }\n };\n\n app.showChatScreen = function () {\n if (!this.chatHistorySection) {\n return;\n }\n\n this.chatHistorySection.classList.remove('show');\n };\n }\n\n function initialize(app, config) {\n if (!app || app.widgetIsInitialized) {\n return;\n }\n\n if (!config.widget.chatWidgetContainer) {\n console.error('The widget chatWidgetContainer is required.');\n return;\n }\n\n if (!config.widget.chatWidgetStateName) {\n console.error('The widget chatWidgetStateName is required.');\n return;\n }\n\n var chatWidgetContainer = document.querySelector(config.widget.chatWidgetContainer);\n if (!chatWidgetContainer) {\n return;\n }\n\n if (config.widget.chatHistorySection) {\n app.chatHistorySection = document.querySelector(config.widget.chatHistorySection);\n }\n\n app.chatWidgetStateName = config.widget.chatWidgetStateName;\n app.chatWidgetStateSession = config.widget.chatWidgetStateName + 'Session';\n app.chatWidgetStateDocuments = config.widget.chatWidgetStateName + 'Documents';\n app.chatWidgetLayoutKey = config.widget.chatWidgetStateName + 'Layout';\n app.widgetContainerElement = chatWidgetContainer;\n app.widgetToggleButtonElement = config.widget.toggleButtonSelector ? document.querySelector(config.widget.toggleButtonSelector) : null;\n app.widgetResetSizeButtonElement = config.widget.resetSizeButtonSelector ? document.querySelector(config.widget.resetSizeButtonSelector) : null;\n app.widgetDefaultWidth = parsePixelValue(config.widget.defaultWidth) || parsePixelValue(window.getComputedStyle(chatWidgetContainer).width) || 380;\n app.widgetDefaultHeight = parsePixelValue(config.widget.defaultHeight) || parsePixelValue(window.getComputedStyle(chatWidgetContainer).height) || 520;\n app.widgetIsInitialized = true;\n app.clearStoredWidgetDocuments();\n app.documents = [];\n\n if (config.widget.enableResizing) {\n chatWidgetContainer.classList.add('ai-chat-widget-resizable');\n chatWidgetContainer.style.minWidth = (parsePixelValue(config.widget.minWidth) || 320) + 'px';\n chatWidgetContainer.style.minHeight = (parsePixelValue(config.widget.minHeight) || 420) + 'px';\n\n if (typeof ResizeObserver !== 'undefined') {\n app.widgetResizeObserver = new ResizeObserver(function () {\n app.persistWidgetPanelSize();\n app.constrainWidgetElementsToViewport();\n app.updateWidgetResetSizeButtonVisibility();\n });\n\n app.widgetResizeObserver.observe(chatWidgetContainer);\n }\n }\n\n var dragHandleSelector = config.widget.dragHandleSelector || '.ai-chat-widget-header';\n var dragHandle = chatWidgetContainer.querySelector(dragHandleSelector);\n\n if (config.widget.enableDragging && dragHandle) {\n dragHandle.classList.add('ai-chat-widget-drag-handle');\n chatWidgetContainer.classList.add('ai-chat-widget-draggable');\n app.attachDraggableWidgetElement(chatWidgetContainer, dragHandle, 'panel', false);\n }\n\n if (config.widget.enableDragging && app.widgetToggleButtonElement) {\n app.widgetToggleButtonElement.classList.add('ai-chat-widget-draggable');\n app.attachDraggableWidgetElement(app.widgetToggleButtonElement, app.widgetToggleButtonElement, 'toggle', true);\n }\n\n if (app.widgetResetSizeButtonElement) {\n app.widgetResetSizeButtonElement.addEventListener('click', function (event) {\n event.preventDefault();\n app.resetWidgetSize();\n });\n }\n\n app.restoreWidgetLayout();\n\n if (!app.widgetViewportResizeHandler) {\n app.widgetViewportResizeHandler = function () {\n if (config.widget.persistLayout) {\n app.restoreWidgetLayout();\n } else {\n app.constrainWidgetElementsToViewport();\n }\n\n app.updateWidgetResetSizeButtonVisibility();\n };\n\n window.addEventListener('resize', app.widgetViewportResizeHandler);\n }\n\n app.reloadCurrentSession();\n\n if (config.widget.showHistoryButton && app.chatHistorySection) {\n var showHistoryButton = document.querySelector(config.widget.showHistoryButton);\n if (showHistoryButton) {\n showHistoryButton.addEventListener('click', function () {\n app.chatHistorySection.classList.toggle('show');\n });\n }\n\n if (config.widget.closeHistoryButton) {\n var closeHistoryButton = document.querySelector(config.widget.closeHistoryButton);\n if (closeHistoryButton) {\n closeHistoryButton.addEventListener('click', function () {\n app.showChatScreen();\n });\n }\n }\n }\n\n if (config.widget.newChatButton) {\n var newChatButton = document.querySelector(config.widget.newChatButton);\n if (newChatButton) {\n newChatButton.addEventListener('click', function () {\n app.resetSession();\n app.showChatScreen();\n });\n }\n }\n }\n\n function resolveSessionId(app) {\n if (!app || !app.widgetIsInitialized) {\n return null;\n }\n\n return localStorage.getItem(app.chatWidgetStateSession);\n }\n\n function onSessionInitialized(app, sessionId) {\n if (app && app.widgetIsInitialized) {\n localStorage.setItem(app.chatWidgetStateSession, sessionId);\n }\n }\n\n function onSessionReset(app) {\n if (app && app.widgetIsInitialized) {\n localStorage.removeItem(app.chatWidgetStateSession);\n app.clearStoredWidgetDocuments();\n }\n }\n\n function onDocumentsChanged(app, documents) {\n if (app && app.widgetIsInitialized) {\n app.saveStoredWidgetDocuments(documents);\n }\n }\n\n function handleReceiveError(app) {\n if (app && app.widgetIsInitialized && !app.isSessionStarted && !app._attemptedSessionRecovery) {\n app._attemptedSessionRecovery = true;\n localStorage.removeItem(app.chatWidgetStateSession);\n app.clearStoredWidgetDocuments();\n app.startNewSession();\n }\n }\n\n function dispose(app) {\n if (!app) {\n return;\n }\n\n if (app.widgetResizeObserver) {\n app.widgetResizeObserver.disconnect();\n app.widgetResizeObserver = null;\n }\n\n if (app.widgetViewportResizeHandler) {\n window.removeEventListener('resize', app.widgetViewportResizeHandler);\n app.widgetViewportResizeHandler = null;\n }\n }\n\n return {\n attach: attach,\n initialize: initialize,\n onMounted: initialize,\n resolveSessionId: resolveSessionId,\n onSessionInitialized: onSessionInitialized,\n onSessionReset: onSessionReset,\n onDocumentsChanged: onDocumentsChanged,\n handleReceiveError: handleReceiveError,\n dispose: dispose,\n onBeforeUnmount: dispose\n };\n}();\n\nwindow.coreAIChatWidgetManager = window.coreAIChatWidgetManager || function () {\n function getAttributeValue(element, attributeName) {\n var value = element.getAttribute(attributeName);\n return value === null || value === '' ? null : value;\n }\n\n function parseBooleanAttributeValue(value) {\n if (value === null || value === undefined) {\n return null;\n }\n\n if (typeof value === 'boolean') {\n return value;\n }\n\n var normalized = String(value).trim().toLowerCase();\n if (normalized === 'true') {\n return true;\n }\n\n if (normalized === 'false') {\n return false;\n }\n\n return null;\n }\n\n function parseJsonAttribute(element, attributeName, description) {\n var rawValue = getAttributeValue(element, attributeName);\n if (!rawValue) {\n return null;\n }\n\n try {\n return JSON.parse(rawValue);\n }\n catch (error) {\n console.error('Failed to parse ' + description + ' JSON.', error);\n return null;\n }\n }\n\n function buildOptionsFromDataAttributes(element) {\n var widgetContainerSelector = getAttributeValue(element, 'data-coreai-chat-widget-container-selector');\n if (!widgetContainerSelector) {\n return null;\n }\n\n var chatConfig = null;\n if (window.coreAIChatManager && typeof window.coreAIChatManager.buildConfigFromElement === 'function') {\n chatConfig = window.coreAIChatManager.buildConfigFromElement(element, { allowWidgetHost: true });\n }\n\n var profileId = getAttributeValue(element, 'data-coreai-chat-widget-profile-id');\n var profileName = getAttributeValue(element, 'data-coreai-chat-widget-profile-name');\n var profileDisplayText = getAttributeValue(element, 'data-coreai-chat-widget-profile-display-text');\n var profileWelcomeMessage = getAttributeValue(element, 'data-coreai-chat-widget-profile-welcome-message');\n var profileChatMode = getAttributeValue(element, 'data-coreai-chat-widget-profile-chat-mode');\n var profileTtsVoiceName = getAttributeValue(element, 'data-coreai-chat-widget-profile-tts-voice-name');\n var profileMetricsEnabled = parseBooleanAttributeValue(getAttributeValue(element, 'data-coreai-chat-widget-profile-enable-session-metrics'));\n var profileSessionDocuments = parseBooleanAttributeValue(getAttributeValue(element, 'data-coreai-chat-widget-profile-allow-session-documents'));\n var profile = null;\n\n if (profileId || profileName || profileDisplayText || profileWelcomeMessage || profileChatMode || profileTtsVoiceName || profileMetricsEnabled !== null || profileSessionDocuments !== null) {\n profile = {\n id: profileId,\n name: profileName,\n displayText: profileDisplayText,\n welcomeMessage: profileWelcomeMessage,\n chatMode: profileChatMode,\n ttsVoiceName: profileTtsVoiceName,\n enableSessionMetrics: profileMetricsEnabled === true,\n allowSessionDocuments: profileSessionDocuments === true\n };\n }\n\n var enableDragging = parseBooleanAttributeValue(getAttributeValue(element, 'data-coreai-chat-widget-enable-dragging'));\n var enableResizing = parseBooleanAttributeValue(getAttributeValue(element, 'data-coreai-chat-widget-enable-resizing'));\n var persistLayout = parseBooleanAttributeValue(getAttributeValue(element, 'data-coreai-chat-widget-persist-layout'));\n\n return {\n shellSelector: getAttributeValue(element, 'data-coreai-chat-widget-shell-selector'),\n widgetContainerSelector: widgetContainerSelector,\n toggleButtonSelector: getAttributeValue(element, 'data-coreai-chat-widget-toggle-button-selector'),\n closeButtonSelector: getAttributeValue(element, 'data-coreai-chat-widget-close-button-selector'),\n inputSelector: getAttributeValue(element, 'data-coreai-chat-widget-input-selector'),\n messageTemplateSelector: getAttributeValue(element, 'data-coreai-chat-widget-message-template-selector'),\n indicatorTemplateSelector: getAttributeValue(element, 'data-coreai-chat-widget-indicator-template-selector'),\n profile: profile,\n widgetStateName: getAttributeValue(element, 'data-coreai-chat-widget-state-name'),\n openStateValue: getAttributeValue(element, 'data-coreai-chat-widget-open-state-value'),\n closedStateValue: getAttributeValue(element, 'data-coreai-chat-widget-closed-state-value'),\n openIconHtml: getAttributeValue(element, 'data-coreai-chat-widget-open-icon-html'),\n closedIconHtml: getAttributeValue(element, 'data-coreai-chat-widget-closed-icon-html'),\n chatConfig: chatConfig ? Object.assign({}, chatConfig, {\n widget: Object.assign({}, chatConfig.widget || {}, {\n chatWidgetContainer: widgetContainerSelector,\n chatWidgetStateName: getAttributeValue(element, 'data-coreai-chat-widget-state-name'),\n newChatButton: getAttributeValue(element, 'data-coreai-chat-widget-new-chat-button-selector'),\n toggleButtonSelector: getAttributeValue(element, 'data-coreai-chat-widget-toggle-button-selector'),\n resetSizeButtonSelector: getAttributeValue(element, 'data-coreai-chat-widget-reset-size-button-selector'),\n dragHandleSelector: getAttributeValue(element, 'data-coreai-chat-widget-drag-handle-selector'),\n enableDragging: enableDragging === null ? undefined : enableDragging,\n enableResizing: enableResizing === null ? undefined : enableResizing,\n persistLayout: persistLayout === null ? undefined : persistLayout,\n })\n }) : null\n };\n }\n\n function initialize(options) {\n if (!options) {\n return null;\n }\n\n var chatConfig = options.chatConfig;\n if (!chatConfig && options.configElementSelector) {\n var configElement = document.querySelector(options.configElementSelector);\n chatConfig = configElement ? parseJsonAttribute(configElement, 'data-config', 'AI chat widget config') : null;\n }\n\n if (!chatConfig) {\n return null;\n }\n\n if (options.messageTemplateSelector) {\n var messageTemplate = document.querySelector(options.messageTemplateSelector);\n if (messageTemplate) {\n chatConfig.messageTemplate = messageTemplate.innerHTML;\n }\n }\n\n if (options.indicatorTemplateSelector) {\n var indicatorTemplate = document.querySelector(options.indicatorTemplateSelector);\n if (indicatorTemplate) {\n chatConfig.indicatorTemplate = indicatorTemplate.innerHTML;\n }\n }\n\n var shell = document.querySelector(options.shellSelector);\n var widgetContainer = document.querySelector(options.widgetContainerSelector);\n var toggleButton = document.querySelector(options.toggleButtonSelector);\n var closeButton = document.querySelector(options.closeButtonSelector);\n var profileInput = options.inputSelector ? document.querySelector(options.inputSelector) : null;\n var widgetStateName = options.widgetStateName || chatConfig.widget.chatWidgetStateName;\n var widgetOpenStateKey = options.widgetOpenStateKey || (widgetStateName + 'Open');\n var widgetLayoutKey = widgetStateName + 'Layout';\n var openStateValue = options.openStateValue || 'open';\n var closedStateValue = options.closedStateValue || 'closed';\n\n if (profileInput && options.profile && options.profile.id) {\n profileInput.setAttribute('data-profile-id', options.profile.id);\n }\n\n try {\n var storedLayout = localStorage.getItem(widgetLayoutKey);\n var layout = storedLayout ? JSON.parse(storedLayout) || {} : {};\n var position = layout.position || {};\n var panelLayout = layout.panel || {};\n var toggleLeft = Number(position.left);\n var toggleTop = Number(position.top);\n var isOpen = localStorage.getItem(widgetOpenStateKey) === openStateValue;\n var viewportPadding = 8;\n\n if (shell) {\n shell.dataset.deferReveal = isOpen ? 'true' : 'false';\n shell.dataset.initialOpen = isOpen ? 'true' : 'false';\n }\n\n if (widgetContainer && toggleButton) {\n var toggleSize = 52;\n var panelWidth = Number.isFinite(Number(panelLayout.width))\n ? Number(panelLayout.width)\n : Math.round(parseFloat(window.getComputedStyle(widgetContainer).width) || 380);\n var panelHeight = Number.isFinite(Number(panelLayout.height))\n ? Number(panelLayout.height)\n : Math.round(parseFloat(window.getComputedStyle(widgetContainer).height) || 520);\n var maxLeft = Math.max(viewportPadding, window.innerWidth - toggleSize - viewportPadding);\n var maxTop = Math.max(viewportPadding, window.innerHeight - toggleSize - viewportPadding);\n if (Number.isFinite(Number(position.leftRatio))) {\n toggleLeft = viewportPadding + Math.max(0, maxLeft - viewportPadding) * Number(position.leftRatio);\n }\n if (Number.isFinite(Number(position.topRatio))) {\n toggleTop = viewportPadding + Math.max(0, maxTop - viewportPadding) * Number(position.topRatio);\n }\n if (Number.isFinite(toggleLeft) && Number.isFinite(toggleTop)) {\n toggleLeft = Math.round(clampWidgetValue(toggleLeft, viewportPadding, maxLeft));\n toggleTop = Math.round(clampWidgetValue(toggleTop, viewportPadding, maxTop));\n }\n\n if (Number.isFinite(toggleLeft) && Number.isFinite(toggleTop)) {\n toggleButton.style.left = toggleLeft + 'px';\n toggleButton.style.top = toggleTop + 'px';\n toggleButton.style.right = 'auto';\n toggleButton.style.bottom = 'auto';\n\n var toggleGap = 8;\n widgetContainer.style.left = (toggleLeft + toggleSize - panelWidth) + 'px';\n widgetContainer.style.top = (toggleTop - panelHeight - toggleGap) + 'px';\n widgetContainer.style.right = 'auto';\n widgetContainer.style.bottom = 'auto';\n }\n }\n\n if (widgetContainer) {\n widgetContainer.classList.remove('open');\n widgetContainer.style.display = 'none';\n widgetContainer.setAttribute('aria-hidden', 'true');\n }\n\n if (toggleButton) {\n toggleButton.innerHTML = isOpen ? options.openIconHtml : options.closedIconHtml;\n }\n }\n catch (error) {\n console.warn('Failed to restore widget layout before initialization.', error);\n }\n finally {\n if (shell && shell.dataset.deferReveal !== 'true') {\n shell.style.visibility = '';\n }\n }\n\n var widgetApp = window.coreAIChatManager.initialize(chatConfig);\n if (options.applySessionProfilePatch !== false && window.crestAppsAIChat && window.crestAppsAIChat.patchSessionProfileSync) {\n window.crestAppsAIChat.patchSessionProfileSync(widgetApp);\n }\n\n function revealShell() {\n if (!shell) {\n return;\n }\n\n shell.style.visibility = '';\n shell.dataset.deferReveal = 'false';\n }\n\n function syncOpenPanelPosition() {\n if (!widgetApp || typeof widgetApp.syncPanelPositionToToggle !== 'function') {\n return;\n }\n\n widgetApp.syncPanelPositionToToggle(false);\n }\n\n function updateTtsPlaybackButtons() {\n if (!widgetContainer) {\n return;\n }\n\n var buttons = widgetContainer.querySelectorAll('[data-tts-message-index]');\n buttons.forEach(function (button) {\n var buttonIndex = Number(button.getAttribute('data-tts-message-index'));\n var isPlaying = buttonIndex === widgetApp.ttsPlayingMessageIndex;\n button.classList.toggle('tts-playing', isPlaying);\n button.setAttribute('title', isPlaying ? 'Pause audio' : 'Read aloud');\n });\n }\n\n function queueTtsPlaybackButtonUpdate() {\n requestAnimationFrame(updateTtsPlaybackButtons);\n }\n\n function revealShellWhenStable(initialOpen) {\n if (!shell || shell.dataset.deferReveal !== 'true' || !initialOpen) {\n revealShell();\n return;\n }\n\n var hasRevealed = false;\n var resizeObserver = null;\n\n function finalizeReveal() {\n if (hasRevealed) {\n return;\n }\n\n hasRevealed = true;\n\n if (resizeObserver) {\n resizeObserver.disconnect();\n }\n\n requestAnimationFrame(function () {\n syncOpenPanelPosition();\n requestAnimationFrame(function () {\n revealShell();\n });\n });\n }\n\n if (typeof ResizeObserver === 'undefined') {\n window.setTimeout(finalizeReveal, 0);\n return;\n }\n\n var lastWidth = 0;\n var lastHeight = 0;\n var stablePasses = 0;\n\n resizeObserver = new ResizeObserver(function (entries) {\n var entry = entries && entries[0];\n if (!entry) {\n return;\n }\n\n var width = Math.round(entry.contentRect.width);\n var height = Math.round(entry.contentRect.height);\n if (!width || !height) {\n return;\n }\n\n syncOpenPanelPosition();\n\n if (width === lastWidth && height === lastHeight) {\n stablePasses++;\n }\n else {\n lastWidth = width;\n lastHeight = height;\n stablePasses = 0;\n }\n\n if (stablePasses >= 1) {\n finalizeReveal();\n }\n });\n\n resizeObserver.observe(widgetContainer);\n window.setTimeout(finalizeReveal, 150);\n }\n\n function setWidgetOpen(isOpen) {\n if (widgetApp) {\n var isCurrentlyOpen = widgetContainer.classList.contains('open');\n if (isOpen && !isCurrentlyOpen && typeof widgetApp.syncPanelPositionToToggle === 'function') {\n widgetApp.syncPanelPositionToToggle();\n }\n else if (!isOpen && isCurrentlyOpen && typeof widgetApp.syncTogglePositionToPanel === 'function') {\n widgetApp.syncTogglePositionToPanel();\n }\n }\n\n widgetContainer.classList.toggle('open', isOpen);\n widgetContainer.style.display = isOpen ? 'flex' : 'none';\n widgetContainer.setAttribute('aria-hidden', isOpen ? 'false' : 'true');\n toggleButton.innerHTML = isOpen ? options.openIconHtml : options.closedIconHtml;\n localStorage.setItem(widgetOpenStateKey, isOpen ? openStateValue : closedStateValue);\n\n if (isOpen && typeof window.renderPendingCharts === 'function') {\n setTimeout(function () { window.renderPendingCharts(); }, 100);\n }\n }\n\n var initialOpen = shell && shell.dataset.initialOpen === 'true';\n setWidgetOpen(initialOpen);\n revealShellWhenStable(initialOpen);\n\n if (widgetApp && typeof widgetApp.$watch === 'function') {\n widgetApp.$watch('ttsPlayingMessageIndex', function () {\n queueTtsPlaybackButtonUpdate();\n });\n }\n\n queueTtsPlaybackButtonUpdate();\n\n if (toggleButton) {\n toggleButton.addEventListener('click', function () {\n if (toggleButton.dataset.dragSuppressClick === 'true') {\n toggleButton.dataset.dragSuppressClick = 'false';\n return;\n }\n\n setWidgetOpen(!widgetContainer.classList.contains('open'));\n });\n }\n\n if (closeButton) {\n closeButton.addEventListener('click', function () {\n setWidgetOpen(false);\n });\n }\n\n return widgetApp;\n }\n\n function initializeFromElement(element) {\n if (!element || element.dataset.coreAiChatWidgetInitialized === 'true') {\n return element ? element.__coreAIChatWidgetApp || null : null;\n }\n\n var jsonOptions = parseJsonAttribute(element, 'data-coreai-chat-widget-config', 'CoreAI chat widget config');\n var attributeOptions = buildOptionsFromDataAttributes(element);\n if (!jsonOptions && !attributeOptions) {\n return null;\n }\n\n var options = Object.assign({}, jsonOptions || {}, attributeOptions || {});\n\n var widgetApp = initialize(options);\n if (!widgetApp) {\n return null;\n }\n\n element.dataset.coreAiChatWidgetInitialized = 'true';\n element.__coreAIChatWidgetApp = widgetApp;\n\n return widgetApp;\n }\n\n function scanForAutoInitialization(root) {\n if (!root || typeof root.querySelectorAll !== 'function') {\n return;\n }\n\n if (typeof root.matches === 'function' && root.matches('[data-coreai-chat-widget-config],[data-coreai-chat-widget-container-selector]')) {\n initializeFromElement(root);\n }\n\n root.querySelectorAll('[data-coreai-chat-widget-config],[data-coreai-chat-widget-container-selector]').forEach(initializeFromElement);\n }\n\n function startAutoInitialization() {\n scanForAutoInitialization(document);\n\n if (typeof MutationObserver === 'undefined') {\n return;\n }\n\n var observer = new MutationObserver(function (mutations) {\n mutations.forEach(function (mutation) {\n mutation.addedNodes.forEach(function (node) {\n if (node && node.nodeType === 1) {\n scanForAutoInitialization(node);\n }\n });\n });\n });\n\n observer.observe(document.body, {\n childList: true,\n subtree: true,\n });\n }\n\n if (document.readyState === 'loading') {\n document.addEventListener('DOMContentLoaded', startAutoInitialization, { once: true });\n } else {\n startAutoInitialization();\n }\n\n return {\n initialize: initialize,\n initializeFromElement: initializeFromElement,\n };\n}();\n"]} diff --git a/src/Resources/CrestApps.AI.Resources/wwwroot/scripts/ai-chat-widget.min.js b/src/Resources/CrestApps.AI.Resources/wwwroot/scripts/ai-chat-widget.min.js index 34f8c539..f271fe1b 100644 --- a/src/Resources/CrestApps.AI.Resources/wwwroot/scripts/ai-chat-widget.min.js +++ b/src/Resources/CrestApps.AI.Resources/wwwroot/scripts/ai-chat-widget.min.js @@ -1,2 +1,2 @@ -function clampWidgetValue(e,t,i){return Math.min(Math.max(e,t),i)}window.coreAIChatWidgetBehavior=window.coreAIChatWidgetBehavior||function(){function e(e){if("number"==typeof e&&Number.isFinite(e))return e;if("string"!=typeof e)return null;var t=parseFloat(e);return Number.isFinite(t)?t:null}function t(t,i){if(t&&!t.widgetIsInitialized)if(i.widget.chatWidgetContainer)if(i.widget.chatWidgetStateName){var n=document.querySelector(i.widget.chatWidgetContainer);if(n){i.widget.chatHistorySection&&(t.chatHistorySection=document.querySelector(i.widget.chatHistorySection)),t.chatWidgetStateName=i.widget.chatWidgetStateName,t.chatWidgetStateSession=i.widget.chatWidgetStateName+"Session",t.chatWidgetStateDocuments=i.widget.chatWidgetStateName+"Documents",t.chatWidgetLayoutKey=i.widget.chatWidgetStateName+"Layout",t.widgetContainerElement=n,t.widgetToggleButtonElement=i.widget.toggleButtonSelector?document.querySelector(i.widget.toggleButtonSelector):null,t.widgetResetSizeButtonElement=i.widget.resetSizeButtonSelector?document.querySelector(i.widget.resetSizeButtonSelector):null,t.widgetDefaultWidth=e(i.widget.defaultWidth)||e(window.getComputedStyle(n).width)||380,t.widgetDefaultHeight=e(i.widget.defaultHeight)||e(window.getComputedStyle(n).height)||520,t.widgetIsInitialized=!0,t.clearStoredWidgetDocuments(),t.documents=[],i.widget.enableResizing&&(n.classList.add("ai-chat-widget-resizable"),n.style.minWidth=(e(i.widget.minWidth)||320)+"px",n.style.minHeight=(e(i.widget.minHeight)||420)+"px","undefined"!=typeof ResizeObserver&&(t.widgetResizeObserver=new ResizeObserver(function(){t.persistWidgetPanelSize(),t.constrainWidgetElementsToViewport(),t.updateWidgetResetSizeButtonVisibility()}),t.widgetResizeObserver.observe(n)));var o=i.widget.dragHandleSelector||".ai-chat-widget-header",a=n.querySelector(o);if(i.widget.enableDragging&&a&&(a.classList.add("ai-chat-widget-drag-handle"),n.classList.add("ai-chat-widget-draggable"),t.attachDraggableWidgetElement(n,a,"panel",!1)),i.widget.enableDragging&&t.widgetToggleButtonElement&&(t.widgetToggleButtonElement.classList.add("ai-chat-widget-draggable"),t.attachDraggableWidgetElement(t.widgetToggleButtonElement,t.widgetToggleButtonElement,"toggle",!0)),t.widgetResetSizeButtonElement&&t.widgetResetSizeButtonElement.addEventListener("click",function(e){e.preventDefault(),t.resetWidgetSize()}),t.restoreWidgetLayout(),t.widgetViewportResizeHandler||(t.widgetViewportResizeHandler=function(){i.widget.persistLayout?t.restoreWidgetLayout():t.constrainWidgetElementsToViewport(),t.updateWidgetResetSizeButtonVisibility()},window.addEventListener("resize",t.widgetViewportResizeHandler)),t.reloadCurrentSession(),i.autoCreateSession&&!t.getSessionId()&&t.startNewSession(),i.widget.showHistoryButton&&t.chatHistorySection){var s=document.querySelector(i.widget.showHistoryButton);if(s&&s.addEventListener("click",function(){t.chatHistorySection.classList.toggle("show")}),i.widget.closeHistoryButton){var l=document.querySelector(i.widget.closeHistoryButton);l&&l.addEventListener("click",function(){t.showChatScreen()})}}if(i.widget.newChatButton){var r=document.querySelector(i.widget.newChatButton);r&&r.addEventListener("click",function(){t.resetSession(),t.showChatScreen()})}}}else console.error("The widget chatWidgetStateName is required.");else console.error("The widget chatWidgetContainer is required.")}function i(e){e&&(e.widgetResizeObserver&&(e.widgetResizeObserver.disconnect(),e.widgetResizeObserver=null),e.widgetViewportResizeHandler&&(window.removeEventListener("resize",e.widgetViewportResizeHandler),e.widgetViewportResizeHandler=null))}return{attach:function(t,i){t&&!t.__aiChatWidgetAttached&&(t.__aiChatWidgetAttached=!0,t.chatWidgetStateName=null,t.chatWidgetStateSession=null,t.chatWidgetStateDocuments=null,t.chatWidgetLayoutKey=null,t.chatHistorySection=null,t.widgetContainerElement=null,t.widgetToggleButtonElement=null,t.widgetResetSizeButtonElement=null,t.widgetResizeObserver=null,t.widgetViewportResizeHandler=null,t.widgetDefaultWidth=null,t.widgetDefaultHeight=null,t.widgetIsInitialized=!1,t.getStoredWidgetLayout=function(){if(!this.chatWidgetLayoutKey||!i.widget.persistLayout)return{};try{var e=localStorage.getItem(this.chatWidgetLayoutKey);return e&&JSON.parse(e)||{}}catch(e){return console.warn("Failed to read widget layout state.",e),{}}},t.saveStoredWidgetLayout=function(e){if(this.chatWidgetLayoutKey&&i.widget.persistLayout){var t=this.getStoredWidgetLayout(),n=Object.assign({},t);void 0!==e.panel&&(n.panel=Object.assign({},t.panel||{},e.panel||{})),void 0!==e.position&&(n.position=Object.assign({},t.position||{},e.position||{})),localStorage.setItem(this.chatWidgetLayoutKey,JSON.stringify(n))}},t.getElementSize=function(t,i,n){if(!t)return{width:i||0,height:n||0};var o=t.getBoundingClientRect(),a=window.getComputedStyle(t);return{width:Math.round(o.width||e(a.width)||i||0),height:Math.round(o.height||e(a.height)||n||0)}},t.getElementPosition=function(t){if(!t)return{left:0,top:0};var i=t.getBoundingClientRect(),n=window.getComputedStyle(t),o=e(t.style.left),a=e(t.style.top),s=e(n.left),l=e(n.top),r="none"===n.display;return{left:Math.round(r&&Number.isFinite(o)?o:i.left||o||s||0),top:Math.round(r&&Number.isFinite(a)?a:i.top||a||l||0)}},t.getAvailableWidgetPositionRange=function(e,t){return{padding:8,maxLeft:Math.max(8,window.innerWidth-e-8),maxTop:Math.max(8,window.innerHeight-t-8)}},t.createStoredPosition=function(e,t,i,n){var o=this.getAvailableWidgetPositionRange(i,n),a=Math.max(0,o.maxLeft-o.padding),s=Math.max(0,o.maxTop-o.padding);return{left:Math.round(e),top:Math.round(t),leftRatio:0===a?0:(e-o.padding)/a,topRatio:0===s?0:(t-o.padding)/s}},t.resolveStoredPosition=function(e,t,i){if(!e)return null;var n=this.getAvailableWidgetPositionRange(t,i),o=Number(e.left),a=Number(e.top),s=Number(e.leftRatio),l=Number(e.topRatio);return Number.isFinite(s)&&(o=n.padding+Math.max(0,n.maxLeft-n.padding)*s),Number.isFinite(l)&&(a=n.padding+Math.max(0,n.maxTop-n.padding)*l),Number.isFinite(o)&&Number.isFinite(a)?this.clampWidgetPosition(o,a,t,i):null},t.clampWidgetPosition=function(e,t,i,n){var o=this.getAvailableWidgetPositionRange(i,n);return{left:Math.round(clampWidgetValue(e,o.padding,o.maxLeft)),top:Math.round(clampWidgetValue(t,o.padding,o.maxTop))}},t.getStoredWidgetDocuments=function(){return this.clearStoredWidgetDocuments(),[]},t.saveStoredWidgetDocuments=function(){this.clearStoredWidgetDocuments()},t.clearStoredWidgetDocuments=function(){this.chatWidgetStateDocuments&&localStorage.removeItem(this.chatWidgetStateDocuments)},t.applyAbsolutePosition=function(e,t,i){e&&(e.style.left=t+"px",e.style.top=i+"px",e.style.right="auto",e.style.bottom="auto")},t.getWidgetDefaultSize=function(){return{width:this.widgetDefaultWidth||e(i.widget.defaultWidth)||380,height:this.widgetDefaultHeight||e(i.widget.defaultHeight)||520}},t.getWidgetToggleGap=function(){return 8},t.isWidgetPanelVisible=function(){if(!this.widgetContainerElement)return!1;var e=window.getComputedStyle(this.widgetContainerElement);return this.widgetContainerElement.classList.contains("open")&&"none"!==e.display},t.persistWidgetPanelPosition=function(){if(this.widgetContainerElement&&i.widget.persistLayout){var e=this.getWidgetDefaultSize(),t=this.getElementPosition(this.widgetContainerElement),n=this.getElementSize(this.widgetContainerElement,e.width,e.height),o=this.getElementSize(this.widgetToggleButtonElement,52,52),a=this.clampWidgetPosition(t.left+n.width-o.width,t.top+n.height+this.getWidgetToggleGap(),o.width,o.height);this.saveStoredWidgetLayout({position:this.createStoredPosition(a.left,a.top,o.width,o.height)})}},t.persistWidgetTogglePosition=function(){if(this.widgetToggleButtonElement&&i.widget.persistLayout){var e=this.getElementPosition(this.widgetToggleButtonElement),t=this.getElementSize(this.widgetToggleButtonElement,52,52);this.saveStoredWidgetLayout({position:this.createStoredPosition(e.left,e.top,t.width,t.height)})}},t.persistWidgetPanelSize=function(){if(this.widgetContainerElement&&i.widget.enableResizing&&i.widget.persistLayout){var e=this.getWidgetDefaultSize(),t=this.getElementSize(this.widgetContainerElement,e.width,e.height);this.saveStoredWidgetLayout({panel:{width:Math.abs(t.width-e.width)<=1?null:t.width,height:Math.abs(t.height-e.height)<=1?null:t.height}})}},t.syncTogglePositionToPanel=function(e){if(void 0===e&&(e=!0),this.widgetContainerElement&&this.widgetToggleButtonElement){var t=this.getWidgetDefaultSize(),n=this.getElementSize(this.widgetContainerElement,t.width,t.height),o=this.getElementSize(this.widgetToggleButtonElement,52,52),a=this.getElementPosition(this.widgetContainerElement),s=this.clampWidgetPosition(a.left+n.width-o.width,a.top+n.height+this.getWidgetToggleGap(),o.width,o.height);this.applyAbsolutePosition(this.widgetToggleButtonElement,s.left,s.top),e&&i.widget.persistLayout&&this.persistWidgetTogglePosition()}},t.syncPanelPositionToToggle=function(e){if(void 0===e&&(e=!0),this.widgetContainerElement&&this.widgetToggleButtonElement){var t=this.getWidgetDefaultSize(),n=this.getElementSize(this.widgetContainerElement,t.width,t.height),o=this.getElementSize(this.widgetToggleButtonElement,52,52),a=this.getElementPosition(this.widgetToggleButtonElement),s=this.clampWidgetPosition(a.left+o.width-n.width,a.top-n.height-this.getWidgetToggleGap(),n.width,n.height);this.applyAbsolutePosition(this.widgetContainerElement,s.left,s.top),e&&i.widget.persistLayout&&this.persistWidgetPanelPosition()}},t.updateWidgetResetSizeButtonVisibility=function(){if(this.widgetResetSizeButtonElement)if(i.widget.enableResizing&&this.widgetContainerElement){var e=this.getWidgetDefaultSize(),t=this.getElementSize(this.widgetContainerElement,e.width,e.height),n=Math.abs(t.width-e.width)>1||Math.abs(t.height-e.height)>1||!!this.widgetContainerElement.style.width||!!this.widgetContainerElement.style.height;this.widgetResetSizeButtonElement.classList.toggle("d-none",!n)}else this.widgetResetSizeButtonElement.classList.add("d-none")},t.resetWidgetSize=function(){this.widgetContainerElement&&i.widget.enableResizing&&(this.widgetContainerElement.style.removeProperty("width"),this.widgetContainerElement.style.removeProperty("height"),this.persistWidgetPanelSize(),this.constrainWidgetElementsToViewport(),this.updateWidgetResetSizeButtonVisibility())},t.restoreWidgetLayout=function(){var e=this.getStoredWidgetLayout();this.widgetContainerElement&&i.widget.enableResizing&&(Number.isFinite(e.panel&&e.panel.width)?this.widgetContainerElement.style.width=e.panel.width+"px":this.widgetContainerElement.style.removeProperty("width"),Number.isFinite(e.panel&&e.panel.height)?this.widgetContainerElement.style.height=e.panel.height+"px":this.widgetContainerElement.style.removeProperty("height"));var t=this.getElementSize(this.widgetToggleButtonElement,52,52),n=this.resolveStoredPosition(e.position,t.width,t.height);this.widgetToggleButtonElement&&i.widget.enableDragging&&n?(this.applyAbsolutePosition(this.widgetToggleButtonElement,n.left,n.top),this.syncPanelPositionToToggle(!1)):this.widgetToggleButtonElement&&i.widget.enableDragging&&Number.isFinite(e.toggle&&e.toggle.left)&&Number.isFinite(e.toggle&&e.toggle.top)?(this.applyAbsolutePosition(this.widgetToggleButtonElement,e.toggle.left,e.toggle.top),this.syncPanelPositionToToggle(!1)):this.widgetContainerElement&&i.widget.enableDragging&&Number.isFinite(e.panel&&e.panel.left)&&Number.isFinite(e.panel&&e.panel.top)&&(this.applyAbsolutePosition(this.widgetContainerElement,e.panel.left,e.panel.top),this.syncTogglePositionToPanel(!1)),this.constrainWidgetElementsToViewport(),this.updateWidgetResetSizeButtonVisibility()},t.attachDraggableWidgetElement=function(e,t,n,o){if(e&&t&&i.widget.enableDragging){var a=null,s=0,l=0,r=0,d=0,g=!1,c=this;t.addEventListener("pointerdown",function(i){if(0===i.button&&("panel"!==n||!i.target.closest("button, a, input, textarea, select, option, label"))){var o=e.getBoundingClientRect();s=i.clientX,l=i.clientY,r=o.left,d=o.top,g=!1,a=i.pointerId,e.classList.add("ai-chat-widget-dragging"),t.setPointerCapture&&t.setPointerCapture(i.pointerId),document.addEventListener("pointermove",h),document.addEventListener("pointerup",u),document.addEventListener("pointercancel",u),i.preventDefault()}})}function u(t){null!==a&&(t&&void 0!==t.pointerId&&t.pointerId!==a||(document.removeEventListener("pointermove",h),document.removeEventListener("pointerup",u),document.removeEventListener("pointercancel",u),e.classList.remove("ai-chat-widget-dragging"),a=null,g&&("panel"===n?(c.syncTogglePositionToPanel(!1),c.persistWidgetPanelPosition()):"toggle"===n&&(c.syncPanelPositionToToggle(!1),c.persistWidgetTogglePosition()),i.widget.persistLayout&&(c.persistWidgetPanelPosition(),c.persistWidgetTogglePosition()),o&&(e.dataset.dragSuppressClick="true",window.setTimeout(function(){"true"===e.dataset.dragSuppressClick&&(e.dataset.dragSuppressClick="false")},0)))))}function h(t){if(null!==a&&t.pointerId===a){var i=t.clientX-s,o=t.clientY-l;if(g||!(Math.hypot(i,o)<4)){g=!0;var u=c.getWidgetDefaultSize(),h=c.getElementSize(e,"panel"===n?u.width:52,"panel"===n?u.height:52),w=c.clampWidgetPosition(r+i,d+o,h.width,h.height);c.applyAbsolutePosition(e,w.left,w.top),"panel"===n?c.syncTogglePositionToPanel(!1):"toggle"===n&&c.syncPanelPositionToToggle(!1)}}}},t.constrainWidgetElementsToViewport=function(){if(this.widgetContainerElement&&this.widgetContainerElement.style.left&&this.isWidgetPanelVisible()){var e=this.getWidgetDefaultSize(),t=this.getElementSize(this.widgetContainerElement,e.width,e.height),n=this.getElementPosition(this.widgetContainerElement),o=this.clampWidgetPosition(n.left,n.top,t.width,t.height);this.applyAbsolutePosition(this.widgetContainerElement,o.left,o.top),this.syncTogglePositionToPanel(!1),i.widget.persistLayout&&(this.persistWidgetPanelPosition(),this.persistWidgetTogglePosition())}else if(this.widgetToggleButtonElement&&this.widgetToggleButtonElement.style.left){var a=this.getElementSize(this.widgetToggleButtonElement,52,52),s=this.getElementPosition(this.widgetToggleButtonElement),l=this.clampWidgetPosition(s.left,s.top,a.width,a.height);this.applyAbsolutePosition(this.widgetToggleButtonElement,l.left,l.top),this.syncPanelPositionToToggle(!1),i.widget.persistLayout&&(this.persistWidgetTogglePosition(),this.persistWidgetPanelPosition())}},t.showChatScreen=function(){this.chatHistorySection&&this.chatHistorySection.classList.remove("show")})},initialize:t,onMounted:t,resolveSessionId:function(e){return e&&e.widgetIsInitialized?localStorage.getItem(e.chatWidgetStateSession):null},onSessionInitialized:function(e,t){e&&e.widgetIsInitialized&&localStorage.setItem(e.chatWidgetStateSession,t)},onSessionReset:function(e){e&&e.widgetIsInitialized&&(localStorage.removeItem(e.chatWidgetStateSession),e.clearStoredWidgetDocuments())},onDocumentsChanged:function(e,t){e&&e.widgetIsInitialized&&e.saveStoredWidgetDocuments(t)},handleReceiveError:function(e){e&&e.widgetIsInitialized&&!e.isSessionStarted&&!e._attemptedSessionRecovery&&(e._attemptedSessionRecovery=!0,localStorage.removeItem(e.chatWidgetStateSession),e.clearStoredWidgetDocuments(),e.startNewSession())},dispose:i,onBeforeUnmount:i}}(),window.coreAIChatWidgetManager=window.coreAIChatWidgetManager||function(){function e(e,t){var i=e.getAttribute(t);return null===i||""===i?null:i}function t(e){if(null==e)return null;if("boolean"==typeof e)return e;var t=String(e).trim().toLowerCase();return"true"===t||"false"!==t&&null}function i(t,i,n){var o=e(t,i);if(!o)return null;try{return JSON.parse(o)}catch(e){return console.error("Failed to parse "+n+" JSON.",e),null}}function n(e){if(!e)return null;var t=e.chatConfig;if(!t&&e.configElementSelector){var n=document.querySelector(e.configElementSelector);t=n?i(n,"data-config","AI chat widget config"):null}if(!t)return null;if(e.messageTemplateSelector){var o=document.querySelector(e.messageTemplateSelector);o&&(t.messageTemplate=o.innerHTML)}if(e.indicatorTemplateSelector){var a=document.querySelector(e.indicatorTemplateSelector);a&&(t.indicatorTemplate=a.innerHTML)}var s=document.querySelector(e.shellSelector),l=document.querySelector(e.widgetContainerSelector),r=document.querySelector(e.toggleButtonSelector),d=document.querySelector(e.closeButtonSelector),g=e.inputSelector?document.querySelector(e.inputSelector):null,c=e.widgetStateName||t.widget.chatWidgetStateName,u=e.widgetOpenStateKey||c+"Open",h=c+"Layout",w=e.openStateValue||"open",m=e.closedStateValue||"closed";g&&e.profile&&e.profile.id&&g.setAttribute("data-profile-id",e.profile.id);try{var p=localStorage.getItem(h),f=p&&JSON.parse(p)||{},S=f.position||{},y=f.panel||{},v=Number(S.left),b=Number(S.top),W=localStorage.getItem(u)===w;if(s&&(s.dataset.deferReveal=W?"true":"false",s.dataset.initialOpen=W?"true":"false"),l&&r){var E=Number.isFinite(Number(y.width))?Number(y.width):Math.round(parseFloat(window.getComputedStyle(l).width)||380),P=Number.isFinite(Number(y.height))?Number(y.height):Math.round(parseFloat(window.getComputedStyle(l).height)||520),T=Math.max(8,window.innerWidth-52-8),C=Math.max(8,window.innerHeight-52-8);if(Number.isFinite(Number(S.leftRatio))&&(v=8+Math.max(0,T-8)*Number(S.leftRatio)),Number.isFinite(Number(S.topRatio))&&(b=8+Math.max(0,C-8)*Number(S.topRatio)),Number.isFinite(v)&&Number.isFinite(b)&&(v=Math.round(clampWidgetValue(v,8,T)),b=Math.round(clampWidgetValue(b,8,C))),Number.isFinite(v)&&Number.isFinite(b)){r.style.left=v+"px",r.style.top=b+"px",r.style.right="auto",r.style.bottom="auto";l.style.left=v+52-E+"px",l.style.top=b-P-8+"px",l.style.right="auto",l.style.bottom="auto"}}l&&(l.classList.remove("open"),l.style.display="none",l.setAttribute("aria-hidden","true")),r&&(r.innerHTML=W?e.openIconHtml:e.closedIconHtml)}catch(e){console.warn("Failed to restore widget layout before initialization.",e)}finally{s&&"true"!==s.dataset.deferReveal&&(s.style.visibility="")}var z=window.coreAIChatManager.initialize(t);function L(){s&&(s.style.visibility="",s.dataset.deferReveal="false")}function B(){z&&"function"==typeof z.syncPanelPositionToToggle&&z.syncPanelPositionToToggle(!1)}function R(){l&&l.querySelectorAll("[data-tts-message-index]").forEach(function(e){var t=Number(e.getAttribute("data-tts-message-index"))===z.ttsPlayingMessageIndex;e.classList.toggle("tts-playing",t),e.setAttribute("title",t?"Pause audio":"Read aloud")})}function I(){requestAnimationFrame(R)}function N(t){if(z){var i=l.classList.contains("open");t&&!i&&"function"==typeof z.syncPanelPositionToToggle?z.syncPanelPositionToToggle():!t&&i&&"function"==typeof z.syncTogglePositionToPanel&&z.syncTogglePositionToPanel()}l.classList.toggle("open",t),l.style.display=t?"flex":"none",l.setAttribute("aria-hidden",t?"false":"true"),r.innerHTML=t?e.openIconHtml:e.closedIconHtml,localStorage.setItem(u,t?w:m),t&&"function"==typeof window.renderPendingCharts&&setTimeout(function(){window.renderPendingCharts()},100)}!1!==e.applySessionProfilePatch&&window.crestAppsAIChat&&window.crestAppsAIChat.patchSessionProfileSync&&window.crestAppsAIChat.patchSessionProfileSync(z);var M=s&&"true"===s.dataset.initialOpen;return N(M),function(e){if(s&&"true"===s.dataset.deferReveal&&e){var t=!1,i=null;if("undefined"!=typeof ResizeObserver){var n=0,o=0,a=0;(i=new ResizeObserver(function(e){var t=e&&e[0];if(t){var i=Math.round(t.contentRect.width),s=Math.round(t.contentRect.height);i&&s&&(B(),i===n&&s===o?a++:(n=i,o=s,a=0),a>=1&&r())}})).observe(l),window.setTimeout(r,150)}else window.setTimeout(r,0)}else L();function r(){t||(t=!0,i&&i.disconnect(),requestAnimationFrame(function(){B(),requestAnimationFrame(function(){L()})}))}}(M),z&&"function"==typeof z.$watch&&z.$watch("ttsPlayingMessageIndex",function(){I()}),I(),r&&r.addEventListener("click",function(){"true"!==r.dataset.dragSuppressClick?N(!l.classList.contains("open")):r.dataset.dragSuppressClick="false"}),d&&d.addEventListener("click",function(){N(!1)}),z}function o(o){if(!o||"true"===o.dataset.coreAiChatWidgetInitialized)return o&&o.__coreAIChatWidgetApp||null;var a=i(o,"data-coreai-chat-widget-config","CoreAI chat widget config"),s=function(i){var n=e(i,"data-coreai-chat-widget-container-selector");if(!n)return null;var o=null;window.coreAIChatManager&&"function"==typeof window.coreAIChatManager.buildConfigFromElement&&(o=window.coreAIChatManager.buildConfigFromElement(i,{allowWidgetHost:!0}));var a=e(i,"data-coreai-chat-widget-profile-id"),s=e(i,"data-coreai-chat-widget-profile-name"),l=e(i,"data-coreai-chat-widget-profile-display-text"),r=e(i,"data-coreai-chat-widget-profile-welcome-message"),d=e(i,"data-coreai-chat-widget-profile-chat-mode"),g=e(i,"data-coreai-chat-widget-profile-tts-voice-name"),c=t(e(i,"data-coreai-chat-widget-profile-enable-session-metrics")),u=t(e(i,"data-coreai-chat-widget-profile-allow-session-documents")),h=null;(a||s||l||r||d||g||null!==c||null!==u)&&(h={id:a,name:s,displayText:l,welcomeMessage:r,chatMode:d,ttsVoiceName:g,enableSessionMetrics:!0===c,allowSessionDocuments:!0===u});var w=t(e(i,"data-coreai-chat-widget-enable-dragging")),m=t(e(i,"data-coreai-chat-widget-enable-resizing")),p=t(e(i,"data-coreai-chat-widget-persist-layout"));return{shellSelector:e(i,"data-coreai-chat-widget-shell-selector"),widgetContainerSelector:n,toggleButtonSelector:e(i,"data-coreai-chat-widget-toggle-button-selector"),closeButtonSelector:e(i,"data-coreai-chat-widget-close-button-selector"),inputSelector:e(i,"data-coreai-chat-widget-input-selector"),messageTemplateSelector:e(i,"data-coreai-chat-widget-message-template-selector"),indicatorTemplateSelector:e(i,"data-coreai-chat-widget-indicator-template-selector"),profile:h,widgetStateName:e(i,"data-coreai-chat-widget-state-name"),openStateValue:e(i,"data-coreai-chat-widget-open-state-value"),closedStateValue:e(i,"data-coreai-chat-widget-closed-state-value"),openIconHtml:e(i,"data-coreai-chat-widget-open-icon-html"),closedIconHtml:e(i,"data-coreai-chat-widget-closed-icon-html"),chatConfig:o?Object.assign({},o,{widget:Object.assign({},o.widget||{},{chatWidgetContainer:n,chatWidgetStateName:e(i,"data-coreai-chat-widget-state-name"),newChatButton:e(i,"data-coreai-chat-widget-new-chat-button-selector"),toggleButtonSelector:e(i,"data-coreai-chat-widget-toggle-button-selector"),resetSizeButtonSelector:e(i,"data-coreai-chat-widget-reset-size-button-selector"),dragHandleSelector:e(i,"data-coreai-chat-widget-drag-handle-selector"),enableDragging:null===w?void 0:w,enableResizing:null===m?void 0:m,persistLayout:null===p?void 0:p})}):null}}(o);if(!a&&!s)return null;var l=n(Object.assign({},a||{},s||{}));return l?(o.dataset.coreAiChatWidgetInitialized="true",o.__coreAIChatWidgetApp=l,l):null}function a(e){e&&"function"==typeof e.querySelectorAll&&("function"==typeof e.matches&&e.matches("[data-coreai-chat-widget-config],[data-coreai-chat-widget-container-selector]")&&o(e),e.querySelectorAll("[data-coreai-chat-widget-config],[data-coreai-chat-widget-container-selector]").forEach(o))}function s(){(a(document),"undefined"!=typeof MutationObserver)&&new MutationObserver(function(e){e.forEach(function(e){e.addedNodes.forEach(function(e){e&&1===e.nodeType&&a(e)})})}).observe(document.body,{childList:!0,subtree:!0})}return"loading"===document.readyState?document.addEventListener("DOMContentLoaded",s,{once:!0}):s(),{initialize:n,initializeFromElement:o}}(); +function clampWidgetValue(e,t,i){return Math.min(Math.max(e,t),i)}window.coreAIChatWidgetBehavior=window.coreAIChatWidgetBehavior||function(){function e(e){if("number"==typeof e&&Number.isFinite(e))return e;if("string"!=typeof e)return null;var t=parseFloat(e);return Number.isFinite(t)?t:null}function t(t,i){if(t&&!t.widgetIsInitialized)if(i.widget.chatWidgetContainer)if(i.widget.chatWidgetStateName){var n=document.querySelector(i.widget.chatWidgetContainer);if(n){i.widget.chatHistorySection&&(t.chatHistorySection=document.querySelector(i.widget.chatHistorySection)),t.chatWidgetStateName=i.widget.chatWidgetStateName,t.chatWidgetStateSession=i.widget.chatWidgetStateName+"Session",t.chatWidgetStateDocuments=i.widget.chatWidgetStateName+"Documents",t.chatWidgetLayoutKey=i.widget.chatWidgetStateName+"Layout",t.widgetContainerElement=n,t.widgetToggleButtonElement=i.widget.toggleButtonSelector?document.querySelector(i.widget.toggleButtonSelector):null,t.widgetResetSizeButtonElement=i.widget.resetSizeButtonSelector?document.querySelector(i.widget.resetSizeButtonSelector):null,t.widgetDefaultWidth=e(i.widget.defaultWidth)||e(window.getComputedStyle(n).width)||380,t.widgetDefaultHeight=e(i.widget.defaultHeight)||e(window.getComputedStyle(n).height)||520,t.widgetIsInitialized=!0,t.clearStoredWidgetDocuments(),t.documents=[],i.widget.enableResizing&&(n.classList.add("ai-chat-widget-resizable"),n.style.minWidth=(e(i.widget.minWidth)||320)+"px",n.style.minHeight=(e(i.widget.minHeight)||420)+"px","undefined"!=typeof ResizeObserver&&(t.widgetResizeObserver=new ResizeObserver(function(){t.persistWidgetPanelSize(),t.constrainWidgetElementsToViewport(),t.updateWidgetResetSizeButtonVisibility()}),t.widgetResizeObserver.observe(n)));var o=i.widget.dragHandleSelector||".ai-chat-widget-header",a=n.querySelector(o);if(i.widget.enableDragging&&a&&(a.classList.add("ai-chat-widget-drag-handle"),n.classList.add("ai-chat-widget-draggable"),t.attachDraggableWidgetElement(n,a,"panel",!1)),i.widget.enableDragging&&t.widgetToggleButtonElement&&(t.widgetToggleButtonElement.classList.add("ai-chat-widget-draggable"),t.attachDraggableWidgetElement(t.widgetToggleButtonElement,t.widgetToggleButtonElement,"toggle",!0)),t.widgetResetSizeButtonElement&&t.widgetResetSizeButtonElement.addEventListener("click",function(e){e.preventDefault(),t.resetWidgetSize()}),t.restoreWidgetLayout(),t.widgetViewportResizeHandler||(t.widgetViewportResizeHandler=function(){i.widget.persistLayout?t.restoreWidgetLayout():t.constrainWidgetElementsToViewport(),t.updateWidgetResetSizeButtonVisibility()},window.addEventListener("resize",t.widgetViewportResizeHandler)),t.reloadCurrentSession(),i.widget.showHistoryButton&&t.chatHistorySection){var l=document.querySelector(i.widget.showHistoryButton);if(l&&l.addEventListener("click",function(){t.chatHistorySection.classList.toggle("show")}),i.widget.closeHistoryButton){var s=document.querySelector(i.widget.closeHistoryButton);s&&s.addEventListener("click",function(){t.showChatScreen()})}}if(i.widget.newChatButton){var r=document.querySelector(i.widget.newChatButton);r&&r.addEventListener("click",function(){t.resetSession(),t.showChatScreen()})}}}else console.error("The widget chatWidgetStateName is required.");else console.error("The widget chatWidgetContainer is required.")}function i(e){e&&(e.widgetResizeObserver&&(e.widgetResizeObserver.disconnect(),e.widgetResizeObserver=null),e.widgetViewportResizeHandler&&(window.removeEventListener("resize",e.widgetViewportResizeHandler),e.widgetViewportResizeHandler=null))}return{attach:function(t,i){t&&!t.__aiChatWidgetAttached&&(t.__aiChatWidgetAttached=!0,t.chatWidgetStateName=null,t.chatWidgetStateSession=null,t.chatWidgetStateDocuments=null,t.chatWidgetLayoutKey=null,t.chatHistorySection=null,t.widgetContainerElement=null,t.widgetToggleButtonElement=null,t.widgetResetSizeButtonElement=null,t.widgetResizeObserver=null,t.widgetViewportResizeHandler=null,t.widgetDefaultWidth=null,t.widgetDefaultHeight=null,t.widgetIsInitialized=!1,t.getStoredWidgetLayout=function(){if(!this.chatWidgetLayoutKey||!i.widget.persistLayout)return{};try{var e=localStorage.getItem(this.chatWidgetLayoutKey);return e&&JSON.parse(e)||{}}catch(e){return console.warn("Failed to read widget layout state.",e),{}}},t.saveStoredWidgetLayout=function(e){if(this.chatWidgetLayoutKey&&i.widget.persistLayout){var t=this.getStoredWidgetLayout(),n=Object.assign({},t);void 0!==e.panel&&(n.panel=Object.assign({},t.panel||{},e.panel||{})),void 0!==e.position&&(n.position=Object.assign({},t.position||{},e.position||{})),localStorage.setItem(this.chatWidgetLayoutKey,JSON.stringify(n))}},t.getElementSize=function(t,i,n){if(!t)return{width:i||0,height:n||0};var o=t.getBoundingClientRect(),a=window.getComputedStyle(t);return{width:Math.round(o.width||e(a.width)||i||0),height:Math.round(o.height||e(a.height)||n||0)}},t.getElementPosition=function(t){if(!t)return{left:0,top:0};var i=t.getBoundingClientRect(),n=window.getComputedStyle(t),o=e(t.style.left),a=e(t.style.top),l=e(n.left),s=e(n.top),r="none"===n.display;return{left:Math.round(r&&Number.isFinite(o)?o:i.left||o||l||0),top:Math.round(r&&Number.isFinite(a)?a:i.top||a||s||0)}},t.getAvailableWidgetPositionRange=function(e,t){return{padding:8,maxLeft:Math.max(8,window.innerWidth-e-8),maxTop:Math.max(8,window.innerHeight-t-8)}},t.createStoredPosition=function(e,t,i,n){var o=this.getAvailableWidgetPositionRange(i,n),a=Math.max(0,o.maxLeft-o.padding),l=Math.max(0,o.maxTop-o.padding);return{left:Math.round(e),top:Math.round(t),leftRatio:0===a?0:(e-o.padding)/a,topRatio:0===l?0:(t-o.padding)/l}},t.resolveStoredPosition=function(e,t,i){if(!e)return null;var n=this.getAvailableWidgetPositionRange(t,i),o=Number(e.left),a=Number(e.top),l=Number(e.leftRatio),s=Number(e.topRatio);return Number.isFinite(l)&&(o=n.padding+Math.max(0,n.maxLeft-n.padding)*l),Number.isFinite(s)&&(a=n.padding+Math.max(0,n.maxTop-n.padding)*s),Number.isFinite(o)&&Number.isFinite(a)?this.clampWidgetPosition(o,a,t,i):null},t.clampWidgetPosition=function(e,t,i,n){var o=this.getAvailableWidgetPositionRange(i,n);return{left:Math.round(clampWidgetValue(e,o.padding,o.maxLeft)),top:Math.round(clampWidgetValue(t,o.padding,o.maxTop))}},t.getStoredWidgetDocuments=function(){return this.clearStoredWidgetDocuments(),[]},t.saveStoredWidgetDocuments=function(){this.clearStoredWidgetDocuments()},t.clearStoredWidgetDocuments=function(){this.chatWidgetStateDocuments&&localStorage.removeItem(this.chatWidgetStateDocuments)},t.applyAbsolutePosition=function(e,t,i){e&&(e.style.left=t+"px",e.style.top=i+"px",e.style.right="auto",e.style.bottom="auto")},t.getWidgetDefaultSize=function(){return{width:this.widgetDefaultWidth||e(i.widget.defaultWidth)||380,height:this.widgetDefaultHeight||e(i.widget.defaultHeight)||520}},t.getWidgetToggleGap=function(){return 8},t.isWidgetPanelVisible=function(){if(!this.widgetContainerElement)return!1;var e=window.getComputedStyle(this.widgetContainerElement);return this.widgetContainerElement.classList.contains("open")&&"none"!==e.display},t.persistWidgetPanelPosition=function(){if(this.widgetContainerElement&&i.widget.persistLayout){var e=this.getWidgetDefaultSize(),t=this.getElementPosition(this.widgetContainerElement),n=this.getElementSize(this.widgetContainerElement,e.width,e.height),o=this.getElementSize(this.widgetToggleButtonElement,52,52),a=this.clampWidgetPosition(t.left+n.width-o.width,t.top+n.height+this.getWidgetToggleGap(),o.width,o.height);this.saveStoredWidgetLayout({position:this.createStoredPosition(a.left,a.top,o.width,o.height)})}},t.persistWidgetTogglePosition=function(){if(this.widgetToggleButtonElement&&i.widget.persistLayout){var e=this.getElementPosition(this.widgetToggleButtonElement),t=this.getElementSize(this.widgetToggleButtonElement,52,52);this.saveStoredWidgetLayout({position:this.createStoredPosition(e.left,e.top,t.width,t.height)})}},t.persistWidgetPanelSize=function(){if(this.widgetContainerElement&&i.widget.enableResizing&&i.widget.persistLayout){var e=this.getWidgetDefaultSize(),t=this.getElementSize(this.widgetContainerElement,e.width,e.height);this.saveStoredWidgetLayout({panel:{width:Math.abs(t.width-e.width)<=1?null:t.width,height:Math.abs(t.height-e.height)<=1?null:t.height}})}},t.syncTogglePositionToPanel=function(e){if(void 0===e&&(e=!0),this.widgetContainerElement&&this.widgetToggleButtonElement){var t=this.getWidgetDefaultSize(),n=this.getElementSize(this.widgetContainerElement,t.width,t.height),o=this.getElementSize(this.widgetToggleButtonElement,52,52),a=this.getElementPosition(this.widgetContainerElement),l=this.clampWidgetPosition(a.left+n.width-o.width,a.top+n.height+this.getWidgetToggleGap(),o.width,o.height);this.applyAbsolutePosition(this.widgetToggleButtonElement,l.left,l.top),e&&i.widget.persistLayout&&this.persistWidgetTogglePosition()}},t.syncPanelPositionToToggle=function(e){if(void 0===e&&(e=!0),this.widgetContainerElement&&this.widgetToggleButtonElement){var t=this.getWidgetDefaultSize(),n=this.getElementSize(this.widgetContainerElement,t.width,t.height),o=this.getElementSize(this.widgetToggleButtonElement,52,52),a=this.getElementPosition(this.widgetToggleButtonElement),l=this.clampWidgetPosition(a.left+o.width-n.width,a.top-n.height-this.getWidgetToggleGap(),n.width,n.height);this.applyAbsolutePosition(this.widgetContainerElement,l.left,l.top),e&&i.widget.persistLayout&&this.persistWidgetPanelPosition()}},t.updateWidgetResetSizeButtonVisibility=function(){if(this.widgetResetSizeButtonElement)if(i.widget.enableResizing&&this.widgetContainerElement){var e=this.getWidgetDefaultSize(),t=this.getElementSize(this.widgetContainerElement,e.width,e.height),n=Math.abs(t.width-e.width)>1||Math.abs(t.height-e.height)>1||!!this.widgetContainerElement.style.width||!!this.widgetContainerElement.style.height;this.widgetResetSizeButtonElement.classList.toggle("d-none",!n)}else this.widgetResetSizeButtonElement.classList.add("d-none")},t.resetWidgetSize=function(){this.widgetContainerElement&&i.widget.enableResizing&&(this.widgetContainerElement.style.removeProperty("width"),this.widgetContainerElement.style.removeProperty("height"),this.persistWidgetPanelSize(),this.constrainWidgetElementsToViewport(),this.updateWidgetResetSizeButtonVisibility())},t.restoreWidgetLayout=function(){var e=this.getStoredWidgetLayout();this.widgetContainerElement&&i.widget.enableResizing&&(Number.isFinite(e.panel&&e.panel.width)?this.widgetContainerElement.style.width=e.panel.width+"px":this.widgetContainerElement.style.removeProperty("width"),Number.isFinite(e.panel&&e.panel.height)?this.widgetContainerElement.style.height=e.panel.height+"px":this.widgetContainerElement.style.removeProperty("height"));var t=this.getElementSize(this.widgetToggleButtonElement,52,52),n=this.resolveStoredPosition(e.position,t.width,t.height);this.widgetToggleButtonElement&&i.widget.enableDragging&&n?(this.applyAbsolutePosition(this.widgetToggleButtonElement,n.left,n.top),this.syncPanelPositionToToggle(!1)):this.widgetToggleButtonElement&&i.widget.enableDragging&&Number.isFinite(e.toggle&&e.toggle.left)&&Number.isFinite(e.toggle&&e.toggle.top)?(this.applyAbsolutePosition(this.widgetToggleButtonElement,e.toggle.left,e.toggle.top),this.syncPanelPositionToToggle(!1)):this.widgetContainerElement&&i.widget.enableDragging&&Number.isFinite(e.panel&&e.panel.left)&&Number.isFinite(e.panel&&e.panel.top)&&(this.applyAbsolutePosition(this.widgetContainerElement,e.panel.left,e.panel.top),this.syncTogglePositionToPanel(!1)),this.constrainWidgetElementsToViewport(),this.updateWidgetResetSizeButtonVisibility()},t.attachDraggableWidgetElement=function(e,t,n,o){if(e&&t&&i.widget.enableDragging){var a=null,l=0,s=0,r=0,d=0,g=!1,c=this;t.addEventListener("pointerdown",function(i){if(0===i.button&&("panel"!==n||!i.target.closest("button, a, input, textarea, select, option, label"))){var o=e.getBoundingClientRect();l=i.clientX,s=i.clientY,r=o.left,d=o.top,g=!1,a=i.pointerId,e.classList.add("ai-chat-widget-dragging"),t.setPointerCapture&&t.setPointerCapture(i.pointerId),document.addEventListener("pointermove",h),document.addEventListener("pointerup",u),document.addEventListener("pointercancel",u),i.preventDefault()}})}function u(t){null!==a&&(t&&void 0!==t.pointerId&&t.pointerId!==a||(document.removeEventListener("pointermove",h),document.removeEventListener("pointerup",u),document.removeEventListener("pointercancel",u),e.classList.remove("ai-chat-widget-dragging"),a=null,g&&("panel"===n?(c.syncTogglePositionToPanel(!1),c.persistWidgetPanelPosition()):"toggle"===n&&(c.syncPanelPositionToToggle(!1),c.persistWidgetTogglePosition()),i.widget.persistLayout&&(c.persistWidgetPanelPosition(),c.persistWidgetTogglePosition()),o&&(e.dataset.dragSuppressClick="true",window.setTimeout(function(){"true"===e.dataset.dragSuppressClick&&(e.dataset.dragSuppressClick="false")},0)))))}function h(t){if(null!==a&&t.pointerId===a){var i=t.clientX-l,o=t.clientY-s;if(g||!(Math.hypot(i,o)<4)){g=!0;var u=c.getWidgetDefaultSize(),h=c.getElementSize(e,"panel"===n?u.width:52,"panel"===n?u.height:52),w=c.clampWidgetPosition(r+i,d+o,h.width,h.height);c.applyAbsolutePosition(e,w.left,w.top),"panel"===n?c.syncTogglePositionToPanel(!1):"toggle"===n&&c.syncPanelPositionToToggle(!1)}}}},t.constrainWidgetElementsToViewport=function(){if(this.widgetContainerElement&&this.widgetContainerElement.style.left&&this.isWidgetPanelVisible()){var e=this.getWidgetDefaultSize(),t=this.getElementSize(this.widgetContainerElement,e.width,e.height),n=this.getElementPosition(this.widgetContainerElement),o=this.clampWidgetPosition(n.left,n.top,t.width,t.height);this.applyAbsolutePosition(this.widgetContainerElement,o.left,o.top),this.syncTogglePositionToPanel(!1),i.widget.persistLayout&&(this.persistWidgetPanelPosition(),this.persistWidgetTogglePosition())}else if(this.widgetToggleButtonElement&&this.widgetToggleButtonElement.style.left){var a=this.getElementSize(this.widgetToggleButtonElement,52,52),l=this.getElementPosition(this.widgetToggleButtonElement),s=this.clampWidgetPosition(l.left,l.top,a.width,a.height);this.applyAbsolutePosition(this.widgetToggleButtonElement,s.left,s.top),this.syncPanelPositionToToggle(!1),i.widget.persistLayout&&(this.persistWidgetTogglePosition(),this.persistWidgetPanelPosition())}},t.showChatScreen=function(){this.chatHistorySection&&this.chatHistorySection.classList.remove("show")})},initialize:t,onMounted:t,resolveSessionId:function(e){return e&&e.widgetIsInitialized?localStorage.getItem(e.chatWidgetStateSession):null},onSessionInitialized:function(e,t){e&&e.widgetIsInitialized&&localStorage.setItem(e.chatWidgetStateSession,t)},onSessionReset:function(e){e&&e.widgetIsInitialized&&(localStorage.removeItem(e.chatWidgetStateSession),e.clearStoredWidgetDocuments())},onDocumentsChanged:function(e,t){e&&e.widgetIsInitialized&&e.saveStoredWidgetDocuments(t)},handleReceiveError:function(e){e&&e.widgetIsInitialized&&!e.isSessionStarted&&!e._attemptedSessionRecovery&&(e._attemptedSessionRecovery=!0,localStorage.removeItem(e.chatWidgetStateSession),e.clearStoredWidgetDocuments(),e.startNewSession())},dispose:i,onBeforeUnmount:i}}(),window.coreAIChatWidgetManager=window.coreAIChatWidgetManager||function(){function e(e,t){var i=e.getAttribute(t);return null===i||""===i?null:i}function t(e){if(null==e)return null;if("boolean"==typeof e)return e;var t=String(e).trim().toLowerCase();return"true"===t||"false"!==t&&null}function i(t,i,n){var o=e(t,i);if(!o)return null;try{return JSON.parse(o)}catch(e){return console.error("Failed to parse "+n+" JSON.",e),null}}function n(e){if(!e)return null;var t=e.chatConfig;if(!t&&e.configElementSelector){var n=document.querySelector(e.configElementSelector);t=n?i(n,"data-config","AI chat widget config"):null}if(!t)return null;if(e.messageTemplateSelector){var o=document.querySelector(e.messageTemplateSelector);o&&(t.messageTemplate=o.innerHTML)}if(e.indicatorTemplateSelector){var a=document.querySelector(e.indicatorTemplateSelector);a&&(t.indicatorTemplate=a.innerHTML)}var l=document.querySelector(e.shellSelector),s=document.querySelector(e.widgetContainerSelector),r=document.querySelector(e.toggleButtonSelector),d=document.querySelector(e.closeButtonSelector),g=e.inputSelector?document.querySelector(e.inputSelector):null,c=e.widgetStateName||t.widget.chatWidgetStateName,u=e.widgetOpenStateKey||c+"Open",h=c+"Layout",w=e.openStateValue||"open",m=e.closedStateValue||"closed";g&&e.profile&&e.profile.id&&g.setAttribute("data-profile-id",e.profile.id);try{var p=localStorage.getItem(h),f=p&&JSON.parse(p)||{},S=f.position||{},y=f.panel||{},v=Number(S.left),b=Number(S.top),W=localStorage.getItem(u)===w;if(l&&(l.dataset.deferReveal=W?"true":"false",l.dataset.initialOpen=W?"true":"false"),s&&r){var E=Number.isFinite(Number(y.width))?Number(y.width):Math.round(parseFloat(window.getComputedStyle(s).width)||380),P=Number.isFinite(Number(y.height))?Number(y.height):Math.round(parseFloat(window.getComputedStyle(s).height)||520),T=Math.max(8,window.innerWidth-52-8),C=Math.max(8,window.innerHeight-52-8);if(Number.isFinite(Number(S.leftRatio))&&(v=8+Math.max(0,T-8)*Number(S.leftRatio)),Number.isFinite(Number(S.topRatio))&&(b=8+Math.max(0,C-8)*Number(S.topRatio)),Number.isFinite(v)&&Number.isFinite(b)&&(v=Math.round(clampWidgetValue(v,8,T)),b=Math.round(clampWidgetValue(b,8,C))),Number.isFinite(v)&&Number.isFinite(b)){r.style.left=v+"px",r.style.top=b+"px",r.style.right="auto",r.style.bottom="auto";s.style.left=v+52-E+"px",s.style.top=b-P-8+"px",s.style.right="auto",s.style.bottom="auto"}}s&&(s.classList.remove("open"),s.style.display="none",s.setAttribute("aria-hidden","true")),r&&(r.innerHTML=W?e.openIconHtml:e.closedIconHtml)}catch(e){console.warn("Failed to restore widget layout before initialization.",e)}finally{l&&"true"!==l.dataset.deferReveal&&(l.style.visibility="")}var z=window.coreAIChatManager.initialize(t);function L(){l&&(l.style.visibility="",l.dataset.deferReveal="false")}function B(){z&&"function"==typeof z.syncPanelPositionToToggle&&z.syncPanelPositionToToggle(!1)}function R(){s&&s.querySelectorAll("[data-tts-message-index]").forEach(function(e){var t=Number(e.getAttribute("data-tts-message-index"))===z.ttsPlayingMessageIndex;e.classList.toggle("tts-playing",t),e.setAttribute("title",t?"Pause audio":"Read aloud")})}function I(){requestAnimationFrame(R)}function N(t){if(z){var i=s.classList.contains("open");t&&!i&&"function"==typeof z.syncPanelPositionToToggle?z.syncPanelPositionToToggle():!t&&i&&"function"==typeof z.syncTogglePositionToPanel&&z.syncTogglePositionToPanel()}s.classList.toggle("open",t),s.style.display=t?"flex":"none",s.setAttribute("aria-hidden",t?"false":"true"),r.innerHTML=t?e.openIconHtml:e.closedIconHtml,localStorage.setItem(u,t?w:m),t&&"function"==typeof window.renderPendingCharts&&setTimeout(function(){window.renderPendingCharts()},100)}!1!==e.applySessionProfilePatch&&window.crestAppsAIChat&&window.crestAppsAIChat.patchSessionProfileSync&&window.crestAppsAIChat.patchSessionProfileSync(z);var M=l&&"true"===l.dataset.initialOpen;return N(M),function(e){if(l&&"true"===l.dataset.deferReveal&&e){var t=!1,i=null;if("undefined"!=typeof ResizeObserver){var n=0,o=0,a=0;(i=new ResizeObserver(function(e){var t=e&&e[0];if(t){var i=Math.round(t.contentRect.width),l=Math.round(t.contentRect.height);i&&l&&(B(),i===n&&l===o?a++:(n=i,o=l,a=0),a>=1&&r())}})).observe(s),window.setTimeout(r,150)}else window.setTimeout(r,0)}else L();function r(){t||(t=!0,i&&i.disconnect(),requestAnimationFrame(function(){B(),requestAnimationFrame(function(){L()})}))}}(M),z&&"function"==typeof z.$watch&&z.$watch("ttsPlayingMessageIndex",function(){I()}),I(),r&&r.addEventListener("click",function(){"true"!==r.dataset.dragSuppressClick?N(!s.classList.contains("open")):r.dataset.dragSuppressClick="false"}),d&&d.addEventListener("click",function(){N(!1)}),z}function o(o){if(!o||"true"===o.dataset.coreAiChatWidgetInitialized)return o&&o.__coreAIChatWidgetApp||null;var a=i(o,"data-coreai-chat-widget-config","CoreAI chat widget config"),l=function(i){var n=e(i,"data-coreai-chat-widget-container-selector");if(!n)return null;var o=null;window.coreAIChatManager&&"function"==typeof window.coreAIChatManager.buildConfigFromElement&&(o=window.coreAIChatManager.buildConfigFromElement(i,{allowWidgetHost:!0}));var a=e(i,"data-coreai-chat-widget-profile-id"),l=e(i,"data-coreai-chat-widget-profile-name"),s=e(i,"data-coreai-chat-widget-profile-display-text"),r=e(i,"data-coreai-chat-widget-profile-welcome-message"),d=e(i,"data-coreai-chat-widget-profile-chat-mode"),g=e(i,"data-coreai-chat-widget-profile-tts-voice-name"),c=t(e(i,"data-coreai-chat-widget-profile-enable-session-metrics")),u=t(e(i,"data-coreai-chat-widget-profile-allow-session-documents")),h=null;(a||l||s||r||d||g||null!==c||null!==u)&&(h={id:a,name:l,displayText:s,welcomeMessage:r,chatMode:d,ttsVoiceName:g,enableSessionMetrics:!0===c,allowSessionDocuments:!0===u});var w=t(e(i,"data-coreai-chat-widget-enable-dragging")),m=t(e(i,"data-coreai-chat-widget-enable-resizing")),p=t(e(i,"data-coreai-chat-widget-persist-layout"));return{shellSelector:e(i,"data-coreai-chat-widget-shell-selector"),widgetContainerSelector:n,toggleButtonSelector:e(i,"data-coreai-chat-widget-toggle-button-selector"),closeButtonSelector:e(i,"data-coreai-chat-widget-close-button-selector"),inputSelector:e(i,"data-coreai-chat-widget-input-selector"),messageTemplateSelector:e(i,"data-coreai-chat-widget-message-template-selector"),indicatorTemplateSelector:e(i,"data-coreai-chat-widget-indicator-template-selector"),profile:h,widgetStateName:e(i,"data-coreai-chat-widget-state-name"),openStateValue:e(i,"data-coreai-chat-widget-open-state-value"),closedStateValue:e(i,"data-coreai-chat-widget-closed-state-value"),openIconHtml:e(i,"data-coreai-chat-widget-open-icon-html"),closedIconHtml:e(i,"data-coreai-chat-widget-closed-icon-html"),chatConfig:o?Object.assign({},o,{widget:Object.assign({},o.widget||{},{chatWidgetContainer:n,chatWidgetStateName:e(i,"data-coreai-chat-widget-state-name"),newChatButton:e(i,"data-coreai-chat-widget-new-chat-button-selector"),toggleButtonSelector:e(i,"data-coreai-chat-widget-toggle-button-selector"),resetSizeButtonSelector:e(i,"data-coreai-chat-widget-reset-size-button-selector"),dragHandleSelector:e(i,"data-coreai-chat-widget-drag-handle-selector"),enableDragging:null===w?void 0:w,enableResizing:null===m?void 0:m,persistLayout:null===p?void 0:p})}):null}}(o);if(!a&&!l)return null;var s=n(Object.assign({},a||{},l||{}));return s?(o.dataset.coreAiChatWidgetInitialized="true",o.__coreAIChatWidgetApp=s,s):null}function a(e){e&&"function"==typeof e.querySelectorAll&&("function"==typeof e.matches&&e.matches("[data-coreai-chat-widget-config],[data-coreai-chat-widget-container-selector]")&&o(e),e.querySelectorAll("[data-coreai-chat-widget-config],[data-coreai-chat-widget-container-selector]").forEach(o))}function l(){(a(document),"undefined"!=typeof MutationObserver)&&new MutationObserver(function(e){e.forEach(function(e){e.addedNodes.forEach(function(e){e&&1===e.nodeType&&a(e)})})}).observe(document.body,{childList:!0,subtree:!0})}return"loading"===document.readyState?document.addEventListener("DOMContentLoaded",l,{once:!0}):l(),{initialize:n,initializeFromElement:o}}(); //# sourceMappingURL=ai-chat-widget.min.js.map diff --git a/src/Resources/CrestApps.AI.Resources/wwwroot/scripts/ai-chat-widget.min.js.map b/src/Resources/CrestApps.AI.Resources/wwwroot/scripts/ai-chat-widget.min.js.map index 845344d3..4ab56698 100644 --- a/src/Resources/CrestApps.AI.Resources/wwwroot/scripts/ai-chat-widget.min.js.map +++ b/src/Resources/CrestApps.AI.Resources/wwwroot/scripts/ai-chat-widget.min.js.map @@ -1 +1 @@ -{"version":3,"sources":["ai-chat-widget.js"],"names":["clampWidgetValue","value","min","max","Math","window","coreAIChatWidgetBehavior","parsePixelValue","Number","isFinite","parsed","parseFloat","initialize","app","config","widgetIsInitialized","widget","chatWidgetContainer","chatWidgetStateName","document","querySelector","chatHistorySection","chatWidgetStateSession","chatWidgetStateDocuments","chatWidgetLayoutKey","widgetContainerElement","widgetToggleButtonElement","toggleButtonSelector","widgetResetSizeButtonElement","resetSizeButtonSelector","widgetDefaultWidth","defaultWidth","getComputedStyle","width","widgetDefaultHeight","defaultHeight","height","clearStoredWidgetDocuments","documents","enableResizing","classList","add","style","minWidth","minHeight","ResizeObserver","widgetResizeObserver","persistWidgetPanelSize","constrainWidgetElementsToViewport","updateWidgetResetSizeButtonVisibility","observe","dragHandleSelector","dragHandle","enableDragging","attachDraggableWidgetElement","addEventListener","event","preventDefault","resetWidgetSize","restoreWidgetLayout","widgetViewportResizeHandler","persistLayout","reloadCurrentSession","autoCreateSession","getSessionId","startNewSession","showHistoryButton","toggle","closeHistoryButton","showChatScreen","newChatButton","resetSession","console","error","dispose","disconnect","removeEventListener","attach","__aiChatWidgetAttached","getStoredWidgetLayout","this","storedLayout","localStorage","getItem","JSON","parse","warn","saveStoredWidgetLayout","partialLayout","currentLayout","nextLayout","Object","assign","undefined","panel","position","setItem","stringify","getElementSize","element","fallbackWidth","fallbackHeight","rect","getBoundingClientRect","computed","round","getElementPosition","left","top","inlineLeft","inlineTop","computedLeft","computedTop","isHidden","display","getAvailableWidgetPositionRange","padding","maxLeft","innerWidth","maxTop","innerHeight","createStoredPosition","range","leftSpan","topSpan","leftRatio","topRatio","resolveStoredPosition","storedPosition","clampWidgetPosition","getStoredWidgetDocuments","saveStoredWidgetDocuments","removeItem","applyAbsolutePosition","right","bottom","getWidgetDefaultSize","getWidgetToggleGap","isWidgetPanelVisible","contains","persistWidgetPanelPosition","panelDefaultSize","panelPosition","panelSize","toggleSize","linkedPosition","persistWidgetTogglePosition","togglePosition","defaultSize","currentSize","abs","syncTogglePositionToPanel","syncPanelPositionToToggle","isResized","removeProperty","storedTogglePosition","handle","layoutKey","suppressClickOnDrag","activePointerId","startX","startY","startLeft","startTop","dragged","self","button","target","closest","clientX","clientY","pointerId","setPointerCapture","onPointerMove","stopDragging","remove","dataset","dragSuppressClick","setTimeout","deltaX","deltaY","hypot","nextPosition","clampedPanel","clampedToggle","onMounted","resolveSessionId","onSessionInitialized","sessionId","onSessionReset","onDocumentsChanged","handleReceiveError","isSessionStarted","_attemptedSessionRecovery","onBeforeUnmount","coreAIChatWidgetManager","getAttributeValue","attributeName","getAttribute","parseBooleanAttributeValue","normalized","String","trim","toLowerCase","parseJsonAttribute","description","rawValue","options","chatConfig","configElementSelector","configElement","messageTemplateSelector","messageTemplate","innerHTML","indicatorTemplateSelector","indicatorTemplate","shell","shellSelector","widgetContainer","widgetContainerSelector","toggleButton","closeButton","closeButtonSelector","profileInput","inputSelector","widgetStateName","widgetOpenStateKey","widgetLayoutKey","openStateValue","closedStateValue","profile","id","setAttribute","layout","panelLayout","toggleLeft","toggleTop","isOpen","deferReveal","initialOpen","panelWidth","panelHeight","openIconHtml","closedIconHtml","visibility","widgetApp","coreAIChatManager","revealShell","syncOpenPanelPosition","updateTtsPlaybackButtons","querySelectorAll","forEach","isPlaying","ttsPlayingMessageIndex","queueTtsPlaybackButtonUpdate","requestAnimationFrame","setWidgetOpen","isCurrentlyOpen","renderPendingCharts","applySessionProfilePatch","crestAppsAIChat","patchSessionProfileSync","hasRevealed","resizeObserver","lastWidth","lastHeight","stablePasses","entries","entry","contentRect","finalizeReveal","revealShellWhenStable","$watch","initializeFromElement","coreAiChatWidgetInitialized","__coreAIChatWidgetApp","jsonOptions","attributeOptions","buildConfigFromElement","allowWidgetHost","profileId","profileName","profileDisplayText","profileWelcomeMessage","profileChatMode","profileTtsVoiceName","profileMetricsEnabled","profileSessionDocuments","name","displayText","welcomeMessage","chatMode","ttsVoiceName","enableSessionMetrics","allowSessionDocuments","buildOptionsFromDataAttributes","scanForAutoInitialization","root","matches","startAutoInitialization","MutationObserver","mutations","mutation","addedNodes","node","nodeType","body","childList","subtree","readyState","once"],"mappings":"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","file":"ai-chat-widget.min.js","sourcesContent":["function clampWidgetValue(value, min, max) {\n return Math.min(Math.max(value, min), max);\n}\n\nwindow.coreAIChatWidgetBehavior = window.coreAIChatWidgetBehavior || function () {\n function parsePixelValue(value) {\n if (typeof value === 'number' && Number.isFinite(value)) {\n return value;\n }\n\n if (typeof value !== 'string') {\n return null;\n }\n\n var parsed = parseFloat(value);\n return Number.isFinite(parsed) ? parsed : null;\n }\n\n function attach(app, config) {\n if (!app || app.__aiChatWidgetAttached) {\n return;\n }\n\n app.__aiChatWidgetAttached = true;\n app.chatWidgetStateName = null;\n app.chatWidgetStateSession = null;\n app.chatWidgetStateDocuments = null;\n app.chatWidgetLayoutKey = null;\n app.chatHistorySection = null;\n app.widgetContainerElement = null;\n app.widgetToggleButtonElement = null;\n app.widgetResetSizeButtonElement = null;\n app.widgetResizeObserver = null;\n app.widgetViewportResizeHandler = null;\n app.widgetDefaultWidth = null;\n app.widgetDefaultHeight = null;\n app.widgetIsInitialized = false;\n\n app.getStoredWidgetLayout = function () {\n if (!this.chatWidgetLayoutKey || !config.widget.persistLayout) {\n return {};\n }\n\n try {\n var storedLayout = localStorage.getItem(this.chatWidgetLayoutKey);\n return storedLayout ? JSON.parse(storedLayout) || {} : {};\n }\n catch (error) {\n console.warn('Failed to read widget layout state.', error);\n return {};\n }\n };\n\n app.saveStoredWidgetLayout = function (partialLayout) {\n if (!this.chatWidgetLayoutKey || !config.widget.persistLayout) {\n return;\n }\n\n var currentLayout = this.getStoredWidgetLayout();\n var nextLayout = Object.assign({}, currentLayout);\n\n if (partialLayout.panel !== undefined) {\n nextLayout.panel = Object.assign({}, currentLayout.panel || {}, partialLayout.panel || {});\n }\n\n if (partialLayout.position !== undefined) {\n nextLayout.position = Object.assign({}, currentLayout.position || {}, partialLayout.position || {});\n }\n\n localStorage.setItem(this.chatWidgetLayoutKey, JSON.stringify(nextLayout));\n };\n\n app.getElementSize = function (element, fallbackWidth, fallbackHeight) {\n if (!element) {\n return {\n width: fallbackWidth || 0,\n height: fallbackHeight || 0\n };\n }\n\n var rect = element.getBoundingClientRect();\n var computed = window.getComputedStyle(element);\n\n return {\n width: Math.round(rect.width || parsePixelValue(computed.width) || fallbackWidth || 0),\n height: Math.round(rect.height || parsePixelValue(computed.height) || fallbackHeight || 0)\n };\n };\n\n app.getElementPosition = function (element) {\n if (!element) {\n return {\n left: 0,\n top: 0\n };\n }\n\n var rect = element.getBoundingClientRect();\n var computed = window.getComputedStyle(element);\n var inlineLeft = parsePixelValue(element.style.left);\n var inlineTop = parsePixelValue(element.style.top);\n var computedLeft = parsePixelValue(computed.left);\n var computedTop = parsePixelValue(computed.top);\n var isHidden = computed.display === 'none';\n\n return {\n left: Math.round(isHidden && Number.isFinite(inlineLeft) ? inlineLeft : rect.left || inlineLeft || computedLeft || 0),\n top: Math.round(isHidden && Number.isFinite(inlineTop) ? inlineTop : rect.top || inlineTop || computedTop || 0)\n };\n };\n\n app.getAvailableWidgetPositionRange = function (width, height) {\n var viewportPadding = 8;\n return {\n padding: viewportPadding,\n maxLeft: Math.max(viewportPadding, window.innerWidth - width - viewportPadding),\n maxTop: Math.max(viewportPadding, window.innerHeight - height - viewportPadding)\n };\n };\n\n app.createStoredPosition = function (left, top, width, height) {\n var range = this.getAvailableWidgetPositionRange(width, height);\n var leftSpan = Math.max(0, range.maxLeft - range.padding);\n var topSpan = Math.max(0, range.maxTop - range.padding);\n\n return {\n left: Math.round(left),\n top: Math.round(top),\n leftRatio: leftSpan === 0 ? 0 : (left - range.padding) / leftSpan,\n topRatio: topSpan === 0 ? 0 : (top - range.padding) / topSpan\n };\n };\n\n app.resolveStoredPosition = function (storedPosition, width, height) {\n if (!storedPosition) {\n return null;\n }\n\n var range = this.getAvailableWidgetPositionRange(width, height);\n var left = Number(storedPosition.left);\n var top = Number(storedPosition.top);\n var leftRatio = Number(storedPosition.leftRatio);\n var topRatio = Number(storedPosition.topRatio);\n\n if (Number.isFinite(leftRatio)) {\n left = range.padding + Math.max(0, range.maxLeft - range.padding) * leftRatio;\n }\n\n if (Number.isFinite(topRatio)) {\n top = range.padding + Math.max(0, range.maxTop - range.padding) * topRatio;\n }\n\n if (!Number.isFinite(left) || !Number.isFinite(top)) {\n return null;\n }\n\n return this.clampWidgetPosition(left, top, width, height);\n };\n\n app.clampWidgetPosition = function (left, top, width, height) {\n var range = this.getAvailableWidgetPositionRange(width, height);\n\n return {\n left: Math.round(clampWidgetValue(left, range.padding, range.maxLeft)),\n top: Math.round(clampWidgetValue(top, range.padding, range.maxTop))\n };\n };\n\n app.getStoredWidgetDocuments = function () {\n this.clearStoredWidgetDocuments();\n return [];\n };\n\n app.saveStoredWidgetDocuments = function () {\n this.clearStoredWidgetDocuments();\n };\n\n app.clearStoredWidgetDocuments = function () {\n if (!this.chatWidgetStateDocuments) {\n return;\n }\n\n localStorage.removeItem(this.chatWidgetStateDocuments);\n };\n\n app.applyAbsolutePosition = function (element, left, top) {\n if (!element) {\n return;\n }\n\n element.style.left = left + 'px';\n element.style.top = top + 'px';\n element.style.right = 'auto';\n element.style.bottom = 'auto';\n };\n\n app.getWidgetDefaultSize = function () {\n return {\n width: this.widgetDefaultWidth || parsePixelValue(config.widget.defaultWidth) || 380,\n height: this.widgetDefaultHeight || parsePixelValue(config.widget.defaultHeight) || 520\n };\n };\n\n app.getWidgetToggleGap = function () {\n return 8;\n };\n\n app.isWidgetPanelVisible = function () {\n if (!this.widgetContainerElement) {\n return false;\n }\n\n var computed = window.getComputedStyle(this.widgetContainerElement);\n return this.widgetContainerElement.classList.contains('open') && computed.display !== 'none';\n };\n\n app.persistWidgetPanelPosition = function () {\n if (!this.widgetContainerElement || !config.widget.persistLayout) {\n return;\n }\n\n var panelDefaultSize = this.getWidgetDefaultSize();\n var panelPosition = this.getElementPosition(this.widgetContainerElement);\n var panelSize = this.getElementSize(this.widgetContainerElement, panelDefaultSize.width, panelDefaultSize.height);\n var toggleSize = this.getElementSize(this.widgetToggleButtonElement, 52, 52);\n var linkedPosition = this.clampWidgetPosition(\n panelPosition.left + panelSize.width - toggleSize.width,\n panelPosition.top + panelSize.height + this.getWidgetToggleGap(),\n toggleSize.width,\n toggleSize.height);\n\n this.saveStoredWidgetLayout({ position: this.createStoredPosition(linkedPosition.left, linkedPosition.top, toggleSize.width, toggleSize.height) });\n };\n\n app.persistWidgetTogglePosition = function () {\n if (!this.widgetToggleButtonElement || !config.widget.persistLayout) {\n return;\n }\n\n var togglePosition = this.getElementPosition(this.widgetToggleButtonElement);\n var toggleSize = this.getElementSize(this.widgetToggleButtonElement, 52, 52);\n this.saveStoredWidgetLayout({ position: this.createStoredPosition(togglePosition.left, togglePosition.top, toggleSize.width, toggleSize.height) });\n };\n\n app.persistWidgetPanelSize = function () {\n if (!this.widgetContainerElement || !config.widget.enableResizing || !config.widget.persistLayout) {\n return;\n }\n\n var defaultSize = this.getWidgetDefaultSize();\n var currentSize = this.getElementSize(this.widgetContainerElement, defaultSize.width, defaultSize.height);\n\n this.saveStoredWidgetLayout({\n panel: {\n width: Math.abs(currentSize.width - defaultSize.width) <= 1 ? null : currentSize.width,\n height: Math.abs(currentSize.height - defaultSize.height) <= 1 ? null : currentSize.height\n }\n });\n };\n\n app.syncTogglePositionToPanel = function (persistLayout) {\n if (persistLayout === undefined) {\n persistLayout = true;\n }\n\n if (!this.widgetContainerElement || !this.widgetToggleButtonElement) {\n return;\n }\n\n var panelDefaultSize = this.getWidgetDefaultSize();\n var panelSize = this.getElementSize(this.widgetContainerElement, panelDefaultSize.width, panelDefaultSize.height);\n var toggleSize = this.getElementSize(this.widgetToggleButtonElement, 52, 52);\n var panelPosition = this.getElementPosition(this.widgetContainerElement);\n var linkedPosition = this.clampWidgetPosition(\n panelPosition.left + panelSize.width - toggleSize.width,\n panelPosition.top + panelSize.height + this.getWidgetToggleGap(),\n toggleSize.width,\n toggleSize.height);\n\n this.applyAbsolutePosition(this.widgetToggleButtonElement, linkedPosition.left, linkedPosition.top);\n\n if (persistLayout && config.widget.persistLayout) {\n this.persistWidgetTogglePosition();\n }\n };\n\n app.syncPanelPositionToToggle = function (persistLayout) {\n if (persistLayout === undefined) {\n persistLayout = true;\n }\n\n if (!this.widgetContainerElement || !this.widgetToggleButtonElement) {\n return;\n }\n\n var panelDefaultSize = this.getWidgetDefaultSize();\n var panelSize = this.getElementSize(this.widgetContainerElement, panelDefaultSize.width, panelDefaultSize.height);\n var toggleSize = this.getElementSize(this.widgetToggleButtonElement, 52, 52);\n var togglePosition = this.getElementPosition(this.widgetToggleButtonElement);\n var linkedPosition = this.clampWidgetPosition(\n togglePosition.left + toggleSize.width - panelSize.width,\n togglePosition.top - panelSize.height - this.getWidgetToggleGap(),\n panelSize.width,\n panelSize.height);\n\n this.applyAbsolutePosition(this.widgetContainerElement, linkedPosition.left, linkedPosition.top);\n\n if (persistLayout && config.widget.persistLayout) {\n this.persistWidgetPanelPosition();\n }\n };\n\n app.updateWidgetResetSizeButtonVisibility = function () {\n if (!this.widgetResetSizeButtonElement) {\n return;\n }\n\n if (!config.widget.enableResizing || !this.widgetContainerElement) {\n this.widgetResetSizeButtonElement.classList.add('d-none');\n return;\n }\n\n var defaultSize = this.getWidgetDefaultSize();\n var currentSize = this.getElementSize(this.widgetContainerElement, defaultSize.width, defaultSize.height);\n var isResized =\n Math.abs(currentSize.width - defaultSize.width) > 1 ||\n Math.abs(currentSize.height - defaultSize.height) > 1 ||\n !!this.widgetContainerElement.style.width ||\n !!this.widgetContainerElement.style.height;\n\n this.widgetResetSizeButtonElement.classList.toggle('d-none', !isResized);\n };\n\n app.resetWidgetSize = function () {\n if (!this.widgetContainerElement || !config.widget.enableResizing) {\n return;\n }\n\n this.widgetContainerElement.style.removeProperty('width');\n this.widgetContainerElement.style.removeProperty('height');\n this.persistWidgetPanelSize();\n this.constrainWidgetElementsToViewport();\n this.updateWidgetResetSizeButtonVisibility();\n };\n\n app.restoreWidgetLayout = function () {\n var storedLayout = this.getStoredWidgetLayout();\n\n if (this.widgetContainerElement && config.widget.enableResizing) {\n if (Number.isFinite(storedLayout.panel && storedLayout.panel.width)) {\n this.widgetContainerElement.style.width = storedLayout.panel.width + 'px';\n }\n else {\n this.widgetContainerElement.style.removeProperty('width');\n }\n\n if (Number.isFinite(storedLayout.panel && storedLayout.panel.height)) {\n this.widgetContainerElement.style.height = storedLayout.panel.height + 'px';\n }\n else {\n this.widgetContainerElement.style.removeProperty('height');\n }\n }\n\n var toggleSize = this.getElementSize(this.widgetToggleButtonElement, 52, 52);\n var storedTogglePosition = this.resolveStoredPosition(storedLayout.position, toggleSize.width, toggleSize.height);\n if (this.widgetToggleButtonElement && config.widget.enableDragging && storedTogglePosition) {\n this.applyAbsolutePosition(this.widgetToggleButtonElement, storedTogglePosition.left, storedTogglePosition.top);\n this.syncPanelPositionToToggle(false);\n }\n else if (this.widgetToggleButtonElement && config.widget.enableDragging &&\n Number.isFinite(storedLayout.toggle && storedLayout.toggle.left) &&\n Number.isFinite(storedLayout.toggle && storedLayout.toggle.top)) {\n this.applyAbsolutePosition(this.widgetToggleButtonElement, storedLayout.toggle.left, storedLayout.toggle.top);\n this.syncPanelPositionToToggle(false);\n }\n else if (this.widgetContainerElement && config.widget.enableDragging &&\n Number.isFinite(storedLayout.panel && storedLayout.panel.left) &&\n Number.isFinite(storedLayout.panel && storedLayout.panel.top)) {\n this.applyAbsolutePosition(this.widgetContainerElement, storedLayout.panel.left, storedLayout.panel.top);\n this.syncTogglePositionToPanel(false);\n }\n\n this.constrainWidgetElementsToViewport();\n this.updateWidgetResetSizeButtonVisibility();\n };\n\n app.attachDraggableWidgetElement = function (element, handle, layoutKey, suppressClickOnDrag) {\n if (!element || !handle || !config.widget.enableDragging) {\n return;\n }\n\n var activePointerId = null;\n var startX = 0;\n var startY = 0;\n var startLeft = 0;\n var startTop = 0;\n var dragged = false;\n var dragThreshold = 4;\n var interactiveSelector = 'button, a, input, textarea, select, option, label';\n var self = this;\n\n function stopDragging(event) {\n if (activePointerId === null) {\n return;\n }\n\n if (event && event.pointerId !== undefined && event.pointerId !== activePointerId) {\n return;\n }\n\n document.removeEventListener('pointermove', onPointerMove);\n document.removeEventListener('pointerup', stopDragging);\n document.removeEventListener('pointercancel', stopDragging);\n element.classList.remove('ai-chat-widget-dragging');\n activePointerId = null;\n\n if (!dragged) {\n return;\n }\n\n if (layoutKey === 'panel') {\n self.syncTogglePositionToPanel(false);\n self.persistWidgetPanelPosition();\n }\n else if (layoutKey === 'toggle') {\n self.syncPanelPositionToToggle(false);\n self.persistWidgetTogglePosition();\n }\n\n if (config.widget.persistLayout) {\n self.persistWidgetPanelPosition();\n self.persistWidgetTogglePosition();\n }\n\n if (suppressClickOnDrag) {\n element.dataset.dragSuppressClick = 'true';\n window.setTimeout(function () {\n if (element.dataset.dragSuppressClick === 'true') {\n element.dataset.dragSuppressClick = 'false';\n }\n }, 0);\n }\n }\n\n function onPointerMove(event) {\n if (activePointerId === null || event.pointerId !== activePointerId) {\n return;\n }\n\n var deltaX = event.clientX - startX;\n var deltaY = event.clientY - startY;\n\n if (!dragged && Math.hypot(deltaX, deltaY) < dragThreshold) {\n return;\n }\n\n dragged = true;\n\n var defaultSize = self.getWidgetDefaultSize();\n var currentSize = self.getElementSize(\n element,\n layoutKey === 'panel' ? defaultSize.width : 52,\n layoutKey === 'panel' ? defaultSize.height : 52);\n var nextPosition = self.clampWidgetPosition(startLeft + deltaX, startTop + deltaY, currentSize.width, currentSize.height);\n\n self.applyAbsolutePosition(element, nextPosition.left, nextPosition.top);\n\n if (layoutKey === 'panel') {\n self.syncTogglePositionToPanel(false);\n }\n else if (layoutKey === 'toggle') {\n self.syncPanelPositionToToggle(false);\n }\n }\n\n handle.addEventListener('pointerdown', function (event) {\n if (event.button !== 0) {\n return;\n }\n\n if (layoutKey === 'panel' && event.target.closest(interactiveSelector)) {\n return;\n }\n\n var rect = element.getBoundingClientRect();\n startX = event.clientX;\n startY = event.clientY;\n startLeft = rect.left;\n startTop = rect.top;\n dragged = false;\n activePointerId = event.pointerId;\n element.classList.add('ai-chat-widget-dragging');\n\n if (handle.setPointerCapture) {\n handle.setPointerCapture(event.pointerId);\n }\n\n document.addEventListener('pointermove', onPointerMove);\n document.addEventListener('pointerup', stopDragging);\n document.addEventListener('pointercancel', stopDragging);\n event.preventDefault();\n });\n };\n\n app.constrainWidgetElementsToViewport = function () {\n if (this.widgetContainerElement && this.widgetContainerElement.style.left && this.isWidgetPanelVisible()) {\n var panelDefaultSize = this.getWidgetDefaultSize();\n var panelSize = this.getElementSize(this.widgetContainerElement, panelDefaultSize.width, panelDefaultSize.height);\n var panelPosition = this.getElementPosition(this.widgetContainerElement);\n var clampedPanel = this.clampWidgetPosition(panelPosition.left, panelPosition.top, panelSize.width, panelSize.height);\n\n this.applyAbsolutePosition(this.widgetContainerElement, clampedPanel.left, clampedPanel.top);\n this.syncTogglePositionToPanel(false);\n\n if (config.widget.persistLayout) {\n this.persistWidgetPanelPosition();\n this.persistWidgetTogglePosition();\n }\n }\n else if (this.widgetToggleButtonElement && this.widgetToggleButtonElement.style.left) {\n var toggleSize = this.getElementSize(this.widgetToggleButtonElement, 52, 52);\n var togglePosition = this.getElementPosition(this.widgetToggleButtonElement);\n var clampedToggle = this.clampWidgetPosition(togglePosition.left, togglePosition.top, toggleSize.width, toggleSize.height);\n\n this.applyAbsolutePosition(this.widgetToggleButtonElement, clampedToggle.left, clampedToggle.top);\n this.syncPanelPositionToToggle(false);\n\n if (config.widget.persistLayout) {\n this.persistWidgetTogglePosition();\n this.persistWidgetPanelPosition();\n }\n }\n };\n\n app.showChatScreen = function () {\n if (!this.chatHistorySection) {\n return;\n }\n\n this.chatHistorySection.classList.remove('show');\n };\n }\n\n function initialize(app, config) {\n if (!app || app.widgetIsInitialized) {\n return;\n }\n\n if (!config.widget.chatWidgetContainer) {\n console.error('The widget chatWidgetContainer is required.');\n return;\n }\n\n if (!config.widget.chatWidgetStateName) {\n console.error('The widget chatWidgetStateName is required.');\n return;\n }\n\n var chatWidgetContainer = document.querySelector(config.widget.chatWidgetContainer);\n if (!chatWidgetContainer) {\n return;\n }\n\n if (config.widget.chatHistorySection) {\n app.chatHistorySection = document.querySelector(config.widget.chatHistorySection);\n }\n\n app.chatWidgetStateName = config.widget.chatWidgetStateName;\n app.chatWidgetStateSession = config.widget.chatWidgetStateName + 'Session';\n app.chatWidgetStateDocuments = config.widget.chatWidgetStateName + 'Documents';\n app.chatWidgetLayoutKey = config.widget.chatWidgetStateName + 'Layout';\n app.widgetContainerElement = chatWidgetContainer;\n app.widgetToggleButtonElement = config.widget.toggleButtonSelector ? document.querySelector(config.widget.toggleButtonSelector) : null;\n app.widgetResetSizeButtonElement = config.widget.resetSizeButtonSelector ? document.querySelector(config.widget.resetSizeButtonSelector) : null;\n app.widgetDefaultWidth = parsePixelValue(config.widget.defaultWidth) || parsePixelValue(window.getComputedStyle(chatWidgetContainer).width) || 380;\n app.widgetDefaultHeight = parsePixelValue(config.widget.defaultHeight) || parsePixelValue(window.getComputedStyle(chatWidgetContainer).height) || 520;\n app.widgetIsInitialized = true;\n app.clearStoredWidgetDocuments();\n app.documents = [];\n\n if (config.widget.enableResizing) {\n chatWidgetContainer.classList.add('ai-chat-widget-resizable');\n chatWidgetContainer.style.minWidth = (parsePixelValue(config.widget.minWidth) || 320) + 'px';\n chatWidgetContainer.style.minHeight = (parsePixelValue(config.widget.minHeight) || 420) + 'px';\n\n if (typeof ResizeObserver !== 'undefined') {\n app.widgetResizeObserver = new ResizeObserver(function () {\n app.persistWidgetPanelSize();\n app.constrainWidgetElementsToViewport();\n app.updateWidgetResetSizeButtonVisibility();\n });\n\n app.widgetResizeObserver.observe(chatWidgetContainer);\n }\n }\n\n var dragHandleSelector = config.widget.dragHandleSelector || '.ai-chat-widget-header';\n var dragHandle = chatWidgetContainer.querySelector(dragHandleSelector);\n\n if (config.widget.enableDragging && dragHandle) {\n dragHandle.classList.add('ai-chat-widget-drag-handle');\n chatWidgetContainer.classList.add('ai-chat-widget-draggable');\n app.attachDraggableWidgetElement(chatWidgetContainer, dragHandle, 'panel', false);\n }\n\n if (config.widget.enableDragging && app.widgetToggleButtonElement) {\n app.widgetToggleButtonElement.classList.add('ai-chat-widget-draggable');\n app.attachDraggableWidgetElement(app.widgetToggleButtonElement, app.widgetToggleButtonElement, 'toggle', true);\n }\n\n if (app.widgetResetSizeButtonElement) {\n app.widgetResetSizeButtonElement.addEventListener('click', function (event) {\n event.preventDefault();\n app.resetWidgetSize();\n });\n }\n\n app.restoreWidgetLayout();\n\n if (!app.widgetViewportResizeHandler) {\n app.widgetViewportResizeHandler = function () {\n if (config.widget.persistLayout) {\n app.restoreWidgetLayout();\n } else {\n app.constrainWidgetElementsToViewport();\n }\n\n app.updateWidgetResetSizeButtonVisibility();\n };\n\n window.addEventListener('resize', app.widgetViewportResizeHandler);\n }\n\n app.reloadCurrentSession();\n\n if (config.autoCreateSession && !app.getSessionId()) {\n app.startNewSession();\n }\n\n if (config.widget.showHistoryButton && app.chatHistorySection) {\n var showHistoryButton = document.querySelector(config.widget.showHistoryButton);\n if (showHistoryButton) {\n showHistoryButton.addEventListener('click', function () {\n app.chatHistorySection.classList.toggle('show');\n });\n }\n\n if (config.widget.closeHistoryButton) {\n var closeHistoryButton = document.querySelector(config.widget.closeHistoryButton);\n if (closeHistoryButton) {\n closeHistoryButton.addEventListener('click', function () {\n app.showChatScreen();\n });\n }\n }\n }\n\n if (config.widget.newChatButton) {\n var newChatButton = document.querySelector(config.widget.newChatButton);\n if (newChatButton) {\n newChatButton.addEventListener('click', function () {\n app.resetSession();\n app.showChatScreen();\n });\n }\n }\n }\n\n function resolveSessionId(app) {\n if (!app || !app.widgetIsInitialized) {\n return null;\n }\n\n return localStorage.getItem(app.chatWidgetStateSession);\n }\n\n function onSessionInitialized(app, sessionId) {\n if (app && app.widgetIsInitialized) {\n localStorage.setItem(app.chatWidgetStateSession, sessionId);\n }\n }\n\n function onSessionReset(app) {\n if (app && app.widgetIsInitialized) {\n localStorage.removeItem(app.chatWidgetStateSession);\n app.clearStoredWidgetDocuments();\n }\n }\n\n function onDocumentsChanged(app, documents) {\n if (app && app.widgetIsInitialized) {\n app.saveStoredWidgetDocuments(documents);\n }\n }\n\n function handleReceiveError(app) {\n if (app && app.widgetIsInitialized && !app.isSessionStarted && !app._attemptedSessionRecovery) {\n app._attemptedSessionRecovery = true;\n localStorage.removeItem(app.chatWidgetStateSession);\n app.clearStoredWidgetDocuments();\n app.startNewSession();\n }\n }\n\n function dispose(app) {\n if (!app) {\n return;\n }\n\n if (app.widgetResizeObserver) {\n app.widgetResizeObserver.disconnect();\n app.widgetResizeObserver = null;\n }\n\n if (app.widgetViewportResizeHandler) {\n window.removeEventListener('resize', app.widgetViewportResizeHandler);\n app.widgetViewportResizeHandler = null;\n }\n }\n\n return {\n attach: attach,\n initialize: initialize,\n onMounted: initialize,\n resolveSessionId: resolveSessionId,\n onSessionInitialized: onSessionInitialized,\n onSessionReset: onSessionReset,\n onDocumentsChanged: onDocumentsChanged,\n handleReceiveError: handleReceiveError,\n dispose: dispose,\n onBeforeUnmount: dispose\n };\n}();\n\nwindow.coreAIChatWidgetManager = window.coreAIChatWidgetManager || function () {\n function getAttributeValue(element, attributeName) {\n var value = element.getAttribute(attributeName);\n return value === null || value === '' ? null : value;\n }\n\n function parseBooleanAttributeValue(value) {\n if (value === null || value === undefined) {\n return null;\n }\n\n if (typeof value === 'boolean') {\n return value;\n }\n\n var normalized = String(value).trim().toLowerCase();\n if (normalized === 'true') {\n return true;\n }\n\n if (normalized === 'false') {\n return false;\n }\n\n return null;\n }\n\n function parseJsonAttribute(element, attributeName, description) {\n var rawValue = getAttributeValue(element, attributeName);\n if (!rawValue) {\n return null;\n }\n\n try {\n return JSON.parse(rawValue);\n }\n catch (error) {\n console.error('Failed to parse ' + description + ' JSON.', error);\n return null;\n }\n }\n\n function buildOptionsFromDataAttributes(element) {\n var widgetContainerSelector = getAttributeValue(element, 'data-coreai-chat-widget-container-selector');\n if (!widgetContainerSelector) {\n return null;\n }\n\n var chatConfig = null;\n if (window.coreAIChatManager && typeof window.coreAIChatManager.buildConfigFromElement === 'function') {\n chatConfig = window.coreAIChatManager.buildConfigFromElement(element, { allowWidgetHost: true });\n }\n\n var profileId = getAttributeValue(element, 'data-coreai-chat-widget-profile-id');\n var profileName = getAttributeValue(element, 'data-coreai-chat-widget-profile-name');\n var profileDisplayText = getAttributeValue(element, 'data-coreai-chat-widget-profile-display-text');\n var profileWelcomeMessage = getAttributeValue(element, 'data-coreai-chat-widget-profile-welcome-message');\n var profileChatMode = getAttributeValue(element, 'data-coreai-chat-widget-profile-chat-mode');\n var profileTtsVoiceName = getAttributeValue(element, 'data-coreai-chat-widget-profile-tts-voice-name');\n var profileMetricsEnabled = parseBooleanAttributeValue(getAttributeValue(element, 'data-coreai-chat-widget-profile-enable-session-metrics'));\n var profileSessionDocuments = parseBooleanAttributeValue(getAttributeValue(element, 'data-coreai-chat-widget-profile-allow-session-documents'));\n var profile = null;\n\n if (profileId || profileName || profileDisplayText || profileWelcomeMessage || profileChatMode || profileTtsVoiceName || profileMetricsEnabled !== null || profileSessionDocuments !== null) {\n profile = {\n id: profileId,\n name: profileName,\n displayText: profileDisplayText,\n welcomeMessage: profileWelcomeMessage,\n chatMode: profileChatMode,\n ttsVoiceName: profileTtsVoiceName,\n enableSessionMetrics: profileMetricsEnabled === true,\n allowSessionDocuments: profileSessionDocuments === true\n };\n }\n\n var enableDragging = parseBooleanAttributeValue(getAttributeValue(element, 'data-coreai-chat-widget-enable-dragging'));\n var enableResizing = parseBooleanAttributeValue(getAttributeValue(element, 'data-coreai-chat-widget-enable-resizing'));\n var persistLayout = parseBooleanAttributeValue(getAttributeValue(element, 'data-coreai-chat-widget-persist-layout'));\n\n return {\n shellSelector: getAttributeValue(element, 'data-coreai-chat-widget-shell-selector'),\n widgetContainerSelector: widgetContainerSelector,\n toggleButtonSelector: getAttributeValue(element, 'data-coreai-chat-widget-toggle-button-selector'),\n closeButtonSelector: getAttributeValue(element, 'data-coreai-chat-widget-close-button-selector'),\n inputSelector: getAttributeValue(element, 'data-coreai-chat-widget-input-selector'),\n messageTemplateSelector: getAttributeValue(element, 'data-coreai-chat-widget-message-template-selector'),\n indicatorTemplateSelector: getAttributeValue(element, 'data-coreai-chat-widget-indicator-template-selector'),\n profile: profile,\n widgetStateName: getAttributeValue(element, 'data-coreai-chat-widget-state-name'),\n openStateValue: getAttributeValue(element, 'data-coreai-chat-widget-open-state-value'),\n closedStateValue: getAttributeValue(element, 'data-coreai-chat-widget-closed-state-value'),\n openIconHtml: getAttributeValue(element, 'data-coreai-chat-widget-open-icon-html'),\n closedIconHtml: getAttributeValue(element, 'data-coreai-chat-widget-closed-icon-html'),\n chatConfig: chatConfig ? Object.assign({}, chatConfig, {\n widget: Object.assign({}, chatConfig.widget || {}, {\n chatWidgetContainer: widgetContainerSelector,\n chatWidgetStateName: getAttributeValue(element, 'data-coreai-chat-widget-state-name'),\n newChatButton: getAttributeValue(element, 'data-coreai-chat-widget-new-chat-button-selector'),\n toggleButtonSelector: getAttributeValue(element, 'data-coreai-chat-widget-toggle-button-selector'),\n resetSizeButtonSelector: getAttributeValue(element, 'data-coreai-chat-widget-reset-size-button-selector'),\n dragHandleSelector: getAttributeValue(element, 'data-coreai-chat-widget-drag-handle-selector'),\n enableDragging: enableDragging === null ? undefined : enableDragging,\n enableResizing: enableResizing === null ? undefined : enableResizing,\n persistLayout: persistLayout === null ? undefined : persistLayout,\n })\n }) : null\n };\n }\n\n function initialize(options) {\n if (!options) {\n return null;\n }\n\n var chatConfig = options.chatConfig;\n if (!chatConfig && options.configElementSelector) {\n var configElement = document.querySelector(options.configElementSelector);\n chatConfig = configElement ? parseJsonAttribute(configElement, 'data-config', 'AI chat widget config') : null;\n }\n\n if (!chatConfig) {\n return null;\n }\n\n if (options.messageTemplateSelector) {\n var messageTemplate = document.querySelector(options.messageTemplateSelector);\n if (messageTemplate) {\n chatConfig.messageTemplate = messageTemplate.innerHTML;\n }\n }\n\n if (options.indicatorTemplateSelector) {\n var indicatorTemplate = document.querySelector(options.indicatorTemplateSelector);\n if (indicatorTemplate) {\n chatConfig.indicatorTemplate = indicatorTemplate.innerHTML;\n }\n }\n\n var shell = document.querySelector(options.shellSelector);\n var widgetContainer = document.querySelector(options.widgetContainerSelector);\n var toggleButton = document.querySelector(options.toggleButtonSelector);\n var closeButton = document.querySelector(options.closeButtonSelector);\n var profileInput = options.inputSelector ? document.querySelector(options.inputSelector) : null;\n var widgetStateName = options.widgetStateName || chatConfig.widget.chatWidgetStateName;\n var widgetOpenStateKey = options.widgetOpenStateKey || (widgetStateName + 'Open');\n var widgetLayoutKey = widgetStateName + 'Layout';\n var openStateValue = options.openStateValue || 'open';\n var closedStateValue = options.closedStateValue || 'closed';\n\n if (profileInput && options.profile && options.profile.id) {\n profileInput.setAttribute('data-profile-id', options.profile.id);\n }\n\n try {\n var storedLayout = localStorage.getItem(widgetLayoutKey);\n var layout = storedLayout ? JSON.parse(storedLayout) || {} : {};\n var position = layout.position || {};\n var panelLayout = layout.panel || {};\n var toggleLeft = Number(position.left);\n var toggleTop = Number(position.top);\n var isOpen = localStorage.getItem(widgetOpenStateKey) === openStateValue;\n var viewportPadding = 8;\n\n if (shell) {\n shell.dataset.deferReveal = isOpen ? 'true' : 'false';\n shell.dataset.initialOpen = isOpen ? 'true' : 'false';\n }\n\n if (widgetContainer && toggleButton) {\n var toggleSize = 52;\n var panelWidth = Number.isFinite(Number(panelLayout.width))\n ? Number(panelLayout.width)\n : Math.round(parseFloat(window.getComputedStyle(widgetContainer).width) || 380);\n var panelHeight = Number.isFinite(Number(panelLayout.height))\n ? Number(panelLayout.height)\n : Math.round(parseFloat(window.getComputedStyle(widgetContainer).height) || 520);\n var maxLeft = Math.max(viewportPadding, window.innerWidth - toggleSize - viewportPadding);\n var maxTop = Math.max(viewportPadding, window.innerHeight - toggleSize - viewportPadding);\n if (Number.isFinite(Number(position.leftRatio))) {\n toggleLeft = viewportPadding + Math.max(0, maxLeft - viewportPadding) * Number(position.leftRatio);\n }\n if (Number.isFinite(Number(position.topRatio))) {\n toggleTop = viewportPadding + Math.max(0, maxTop - viewportPadding) * Number(position.topRatio);\n }\n if (Number.isFinite(toggleLeft) && Number.isFinite(toggleTop)) {\n toggleLeft = Math.round(clampWidgetValue(toggleLeft, viewportPadding, maxLeft));\n toggleTop = Math.round(clampWidgetValue(toggleTop, viewportPadding, maxTop));\n }\n\n if (Number.isFinite(toggleLeft) && Number.isFinite(toggleTop)) {\n toggleButton.style.left = toggleLeft + 'px';\n toggleButton.style.top = toggleTop + 'px';\n toggleButton.style.right = 'auto';\n toggleButton.style.bottom = 'auto';\n\n var toggleGap = 8;\n widgetContainer.style.left = (toggleLeft + toggleSize - panelWidth) + 'px';\n widgetContainer.style.top = (toggleTop - panelHeight - toggleGap) + 'px';\n widgetContainer.style.right = 'auto';\n widgetContainer.style.bottom = 'auto';\n }\n }\n\n if (widgetContainer) {\n widgetContainer.classList.remove('open');\n widgetContainer.style.display = 'none';\n widgetContainer.setAttribute('aria-hidden', 'true');\n }\n\n if (toggleButton) {\n toggleButton.innerHTML = isOpen ? options.openIconHtml : options.closedIconHtml;\n }\n }\n catch (error) {\n console.warn('Failed to restore widget layout before initialization.', error);\n }\n finally {\n if (shell && shell.dataset.deferReveal !== 'true') {\n shell.style.visibility = '';\n }\n }\n\n var widgetApp = window.coreAIChatManager.initialize(chatConfig);\n if (options.applySessionProfilePatch !== false && window.crestAppsAIChat && window.crestAppsAIChat.patchSessionProfileSync) {\n window.crestAppsAIChat.patchSessionProfileSync(widgetApp);\n }\n\n function revealShell() {\n if (!shell) {\n return;\n }\n\n shell.style.visibility = '';\n shell.dataset.deferReveal = 'false';\n }\n\n function syncOpenPanelPosition() {\n if (!widgetApp || typeof widgetApp.syncPanelPositionToToggle !== 'function') {\n return;\n }\n\n widgetApp.syncPanelPositionToToggle(false);\n }\n\n function updateTtsPlaybackButtons() {\n if (!widgetContainer) {\n return;\n }\n\n var buttons = widgetContainer.querySelectorAll('[data-tts-message-index]');\n buttons.forEach(function (button) {\n var buttonIndex = Number(button.getAttribute('data-tts-message-index'));\n var isPlaying = buttonIndex === widgetApp.ttsPlayingMessageIndex;\n button.classList.toggle('tts-playing', isPlaying);\n button.setAttribute('title', isPlaying ? 'Pause audio' : 'Read aloud');\n });\n }\n\n function queueTtsPlaybackButtonUpdate() {\n requestAnimationFrame(updateTtsPlaybackButtons);\n }\n\n function revealShellWhenStable(initialOpen) {\n if (!shell || shell.dataset.deferReveal !== 'true' || !initialOpen) {\n revealShell();\n return;\n }\n\n var hasRevealed = false;\n var resizeObserver = null;\n\n function finalizeReveal() {\n if (hasRevealed) {\n return;\n }\n\n hasRevealed = true;\n\n if (resizeObserver) {\n resizeObserver.disconnect();\n }\n\n requestAnimationFrame(function () {\n syncOpenPanelPosition();\n requestAnimationFrame(function () {\n revealShell();\n });\n });\n }\n\n if (typeof ResizeObserver === 'undefined') {\n window.setTimeout(finalizeReveal, 0);\n return;\n }\n\n var lastWidth = 0;\n var lastHeight = 0;\n var stablePasses = 0;\n\n resizeObserver = new ResizeObserver(function (entries) {\n var entry = entries && entries[0];\n if (!entry) {\n return;\n }\n\n var width = Math.round(entry.contentRect.width);\n var height = Math.round(entry.contentRect.height);\n if (!width || !height) {\n return;\n }\n\n syncOpenPanelPosition();\n\n if (width === lastWidth && height === lastHeight) {\n stablePasses++;\n }\n else {\n lastWidth = width;\n lastHeight = height;\n stablePasses = 0;\n }\n\n if (stablePasses >= 1) {\n finalizeReveal();\n }\n });\n\n resizeObserver.observe(widgetContainer);\n window.setTimeout(finalizeReveal, 150);\n }\n\n function setWidgetOpen(isOpen) {\n if (widgetApp) {\n var isCurrentlyOpen = widgetContainer.classList.contains('open');\n if (isOpen && !isCurrentlyOpen && typeof widgetApp.syncPanelPositionToToggle === 'function') {\n widgetApp.syncPanelPositionToToggle();\n }\n else if (!isOpen && isCurrentlyOpen && typeof widgetApp.syncTogglePositionToPanel === 'function') {\n widgetApp.syncTogglePositionToPanel();\n }\n }\n\n widgetContainer.classList.toggle('open', isOpen);\n widgetContainer.style.display = isOpen ? 'flex' : 'none';\n widgetContainer.setAttribute('aria-hidden', isOpen ? 'false' : 'true');\n toggleButton.innerHTML = isOpen ? options.openIconHtml : options.closedIconHtml;\n localStorage.setItem(widgetOpenStateKey, isOpen ? openStateValue : closedStateValue);\n\n if (isOpen && typeof window.renderPendingCharts === 'function') {\n setTimeout(function () { window.renderPendingCharts(); }, 100);\n }\n }\n\n var initialOpen = shell && shell.dataset.initialOpen === 'true';\n setWidgetOpen(initialOpen);\n revealShellWhenStable(initialOpen);\n\n if (widgetApp && typeof widgetApp.$watch === 'function') {\n widgetApp.$watch('ttsPlayingMessageIndex', function () {\n queueTtsPlaybackButtonUpdate();\n });\n }\n\n queueTtsPlaybackButtonUpdate();\n\n if (toggleButton) {\n toggleButton.addEventListener('click', function () {\n if (toggleButton.dataset.dragSuppressClick === 'true') {\n toggleButton.dataset.dragSuppressClick = 'false';\n return;\n }\n\n setWidgetOpen(!widgetContainer.classList.contains('open'));\n });\n }\n\n if (closeButton) {\n closeButton.addEventListener('click', function () {\n setWidgetOpen(false);\n });\n }\n\n return widgetApp;\n }\n\n function initializeFromElement(element) {\n if (!element || element.dataset.coreAiChatWidgetInitialized === 'true') {\n return element ? element.__coreAIChatWidgetApp || null : null;\n }\n\n var jsonOptions = parseJsonAttribute(element, 'data-coreai-chat-widget-config', 'CoreAI chat widget config');\n var attributeOptions = buildOptionsFromDataAttributes(element);\n if (!jsonOptions && !attributeOptions) {\n return null;\n }\n\n var options = Object.assign({}, jsonOptions || {}, attributeOptions || {});\n\n var widgetApp = initialize(options);\n if (!widgetApp) {\n return null;\n }\n\n element.dataset.coreAiChatWidgetInitialized = 'true';\n element.__coreAIChatWidgetApp = widgetApp;\n\n return widgetApp;\n }\n\n function scanForAutoInitialization(root) {\n if (!root || typeof root.querySelectorAll !== 'function') {\n return;\n }\n\n if (typeof root.matches === 'function' && root.matches('[data-coreai-chat-widget-config],[data-coreai-chat-widget-container-selector]')) {\n initializeFromElement(root);\n }\n\n root.querySelectorAll('[data-coreai-chat-widget-config],[data-coreai-chat-widget-container-selector]').forEach(initializeFromElement);\n }\n\n function startAutoInitialization() {\n scanForAutoInitialization(document);\n\n if (typeof MutationObserver === 'undefined') {\n return;\n }\n\n var observer = new MutationObserver(function (mutations) {\n mutations.forEach(function (mutation) {\n mutation.addedNodes.forEach(function (node) {\n if (node && node.nodeType === 1) {\n scanForAutoInitialization(node);\n }\n });\n });\n });\n\n observer.observe(document.body, {\n childList: true,\n subtree: true,\n });\n }\n\n if (document.readyState === 'loading') {\n document.addEventListener('DOMContentLoaded', startAutoInitialization, { once: true });\n } else {\n startAutoInitialization();\n }\n\n return {\n initialize: initialize,\n initializeFromElement: initializeFromElement,\n };\n}();\n"]} +{"version":3,"sources":["ai-chat-widget.js"],"names":["clampWidgetValue","value","min","max","Math","window","coreAIChatWidgetBehavior","parsePixelValue","Number","isFinite","parsed","parseFloat","initialize","app","config","widgetIsInitialized","widget","chatWidgetContainer","chatWidgetStateName","document","querySelector","chatHistorySection","chatWidgetStateSession","chatWidgetStateDocuments","chatWidgetLayoutKey","widgetContainerElement","widgetToggleButtonElement","toggleButtonSelector","widgetResetSizeButtonElement","resetSizeButtonSelector","widgetDefaultWidth","defaultWidth","getComputedStyle","width","widgetDefaultHeight","defaultHeight","height","clearStoredWidgetDocuments","documents","enableResizing","classList","add","style","minWidth","minHeight","ResizeObserver","widgetResizeObserver","persistWidgetPanelSize","constrainWidgetElementsToViewport","updateWidgetResetSizeButtonVisibility","observe","dragHandleSelector","dragHandle","enableDragging","attachDraggableWidgetElement","addEventListener","event","preventDefault","resetWidgetSize","restoreWidgetLayout","widgetViewportResizeHandler","persistLayout","reloadCurrentSession","showHistoryButton","toggle","closeHistoryButton","showChatScreen","newChatButton","resetSession","console","error","dispose","disconnect","removeEventListener","attach","__aiChatWidgetAttached","getStoredWidgetLayout","this","storedLayout","localStorage","getItem","JSON","parse","warn","saveStoredWidgetLayout","partialLayout","currentLayout","nextLayout","Object","assign","undefined","panel","position","setItem","stringify","getElementSize","element","fallbackWidth","fallbackHeight","rect","getBoundingClientRect","computed","round","getElementPosition","left","top","inlineLeft","inlineTop","computedLeft","computedTop","isHidden","display","getAvailableWidgetPositionRange","padding","maxLeft","innerWidth","maxTop","innerHeight","createStoredPosition","range","leftSpan","topSpan","leftRatio","topRatio","resolveStoredPosition","storedPosition","clampWidgetPosition","getStoredWidgetDocuments","saveStoredWidgetDocuments","removeItem","applyAbsolutePosition","right","bottom","getWidgetDefaultSize","getWidgetToggleGap","isWidgetPanelVisible","contains","persistWidgetPanelPosition","panelDefaultSize","panelPosition","panelSize","toggleSize","linkedPosition","persistWidgetTogglePosition","togglePosition","defaultSize","currentSize","abs","syncTogglePositionToPanel","syncPanelPositionToToggle","isResized","removeProperty","storedTogglePosition","handle","layoutKey","suppressClickOnDrag","activePointerId","startX","startY","startLeft","startTop","dragged","self","button","target","closest","clientX","clientY","pointerId","setPointerCapture","onPointerMove","stopDragging","remove","dataset","dragSuppressClick","setTimeout","deltaX","deltaY","hypot","nextPosition","clampedPanel","clampedToggle","onMounted","resolveSessionId","onSessionInitialized","sessionId","onSessionReset","onDocumentsChanged","handleReceiveError","isSessionStarted","_attemptedSessionRecovery","startNewSession","onBeforeUnmount","coreAIChatWidgetManager","getAttributeValue","attributeName","getAttribute","parseBooleanAttributeValue","normalized","String","trim","toLowerCase","parseJsonAttribute","description","rawValue","options","chatConfig","configElementSelector","configElement","messageTemplateSelector","messageTemplate","innerHTML","indicatorTemplateSelector","indicatorTemplate","shell","shellSelector","widgetContainer","widgetContainerSelector","toggleButton","closeButton","closeButtonSelector","profileInput","inputSelector","widgetStateName","widgetOpenStateKey","widgetLayoutKey","openStateValue","closedStateValue","profile","id","setAttribute","layout","panelLayout","toggleLeft","toggleTop","isOpen","deferReveal","initialOpen","panelWidth","panelHeight","openIconHtml","closedIconHtml","visibility","widgetApp","coreAIChatManager","revealShell","syncOpenPanelPosition","updateTtsPlaybackButtons","querySelectorAll","forEach","isPlaying","ttsPlayingMessageIndex","queueTtsPlaybackButtonUpdate","requestAnimationFrame","setWidgetOpen","isCurrentlyOpen","renderPendingCharts","applySessionProfilePatch","crestAppsAIChat","patchSessionProfileSync","hasRevealed","resizeObserver","lastWidth","lastHeight","stablePasses","entries","entry","contentRect","finalizeReveal","revealShellWhenStable","$watch","initializeFromElement","coreAiChatWidgetInitialized","__coreAIChatWidgetApp","jsonOptions","attributeOptions","buildConfigFromElement","allowWidgetHost","profileId","profileName","profileDisplayText","profileWelcomeMessage","profileChatMode","profileTtsVoiceName","profileMetricsEnabled","profileSessionDocuments","name","displayText","welcomeMessage","chatMode","ttsVoiceName","enableSessionMetrics","allowSessionDocuments","buildOptionsFromDataAttributes","scanForAutoInitialization","root","matches","startAutoInitialization","MutationObserver","mutations","mutation","addedNodes","node","nodeType","body","childList","subtree","readyState","once"],"mappings":"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","file":"ai-chat-widget.min.js","sourcesContent":["function clampWidgetValue(value, min, max) {\n return Math.min(Math.max(value, min), max);\n}\n\nwindow.coreAIChatWidgetBehavior = window.coreAIChatWidgetBehavior || function () {\n function parsePixelValue(value) {\n if (typeof value === 'number' && Number.isFinite(value)) {\n return value;\n }\n\n if (typeof value !== 'string') {\n return null;\n }\n\n var parsed = parseFloat(value);\n return Number.isFinite(parsed) ? parsed : null;\n }\n\n function attach(app, config) {\n if (!app || app.__aiChatWidgetAttached) {\n return;\n }\n\n app.__aiChatWidgetAttached = true;\n app.chatWidgetStateName = null;\n app.chatWidgetStateSession = null;\n app.chatWidgetStateDocuments = null;\n app.chatWidgetLayoutKey = null;\n app.chatHistorySection = null;\n app.widgetContainerElement = null;\n app.widgetToggleButtonElement = null;\n app.widgetResetSizeButtonElement = null;\n app.widgetResizeObserver = null;\n app.widgetViewportResizeHandler = null;\n app.widgetDefaultWidth = null;\n app.widgetDefaultHeight = null;\n app.widgetIsInitialized = false;\n\n app.getStoredWidgetLayout = function () {\n if (!this.chatWidgetLayoutKey || !config.widget.persistLayout) {\n return {};\n }\n\n try {\n var storedLayout = localStorage.getItem(this.chatWidgetLayoutKey);\n return storedLayout ? JSON.parse(storedLayout) || {} : {};\n }\n catch (error) {\n console.warn('Failed to read widget layout state.', error);\n return {};\n }\n };\n\n app.saveStoredWidgetLayout = function (partialLayout) {\n if (!this.chatWidgetLayoutKey || !config.widget.persistLayout) {\n return;\n }\n\n var currentLayout = this.getStoredWidgetLayout();\n var nextLayout = Object.assign({}, currentLayout);\n\n if (partialLayout.panel !== undefined) {\n nextLayout.panel = Object.assign({}, currentLayout.panel || {}, partialLayout.panel || {});\n }\n\n if (partialLayout.position !== undefined) {\n nextLayout.position = Object.assign({}, currentLayout.position || {}, partialLayout.position || {});\n }\n\n localStorage.setItem(this.chatWidgetLayoutKey, JSON.stringify(nextLayout));\n };\n\n app.getElementSize = function (element, fallbackWidth, fallbackHeight) {\n if (!element) {\n return {\n width: fallbackWidth || 0,\n height: fallbackHeight || 0\n };\n }\n\n var rect = element.getBoundingClientRect();\n var computed = window.getComputedStyle(element);\n\n return {\n width: Math.round(rect.width || parsePixelValue(computed.width) || fallbackWidth || 0),\n height: Math.round(rect.height || parsePixelValue(computed.height) || fallbackHeight || 0)\n };\n };\n\n app.getElementPosition = function (element) {\n if (!element) {\n return {\n left: 0,\n top: 0\n };\n }\n\n var rect = element.getBoundingClientRect();\n var computed = window.getComputedStyle(element);\n var inlineLeft = parsePixelValue(element.style.left);\n var inlineTop = parsePixelValue(element.style.top);\n var computedLeft = parsePixelValue(computed.left);\n var computedTop = parsePixelValue(computed.top);\n var isHidden = computed.display === 'none';\n\n return {\n left: Math.round(isHidden && Number.isFinite(inlineLeft) ? inlineLeft : rect.left || inlineLeft || computedLeft || 0),\n top: Math.round(isHidden && Number.isFinite(inlineTop) ? inlineTop : rect.top || inlineTop || computedTop || 0)\n };\n };\n\n app.getAvailableWidgetPositionRange = function (width, height) {\n var viewportPadding = 8;\n return {\n padding: viewportPadding,\n maxLeft: Math.max(viewportPadding, window.innerWidth - width - viewportPadding),\n maxTop: Math.max(viewportPadding, window.innerHeight - height - viewportPadding)\n };\n };\n\n app.createStoredPosition = function (left, top, width, height) {\n var range = this.getAvailableWidgetPositionRange(width, height);\n var leftSpan = Math.max(0, range.maxLeft - range.padding);\n var topSpan = Math.max(0, range.maxTop - range.padding);\n\n return {\n left: Math.round(left),\n top: Math.round(top),\n leftRatio: leftSpan === 0 ? 0 : (left - range.padding) / leftSpan,\n topRatio: topSpan === 0 ? 0 : (top - range.padding) / topSpan\n };\n };\n\n app.resolveStoredPosition = function (storedPosition, width, height) {\n if (!storedPosition) {\n return null;\n }\n\n var range = this.getAvailableWidgetPositionRange(width, height);\n var left = Number(storedPosition.left);\n var top = Number(storedPosition.top);\n var leftRatio = Number(storedPosition.leftRatio);\n var topRatio = Number(storedPosition.topRatio);\n\n if (Number.isFinite(leftRatio)) {\n left = range.padding + Math.max(0, range.maxLeft - range.padding) * leftRatio;\n }\n\n if (Number.isFinite(topRatio)) {\n top = range.padding + Math.max(0, range.maxTop - range.padding) * topRatio;\n }\n\n if (!Number.isFinite(left) || !Number.isFinite(top)) {\n return null;\n }\n\n return this.clampWidgetPosition(left, top, width, height);\n };\n\n app.clampWidgetPosition = function (left, top, width, height) {\n var range = this.getAvailableWidgetPositionRange(width, height);\n\n return {\n left: Math.round(clampWidgetValue(left, range.padding, range.maxLeft)),\n top: Math.round(clampWidgetValue(top, range.padding, range.maxTop))\n };\n };\n\n app.getStoredWidgetDocuments = function () {\n this.clearStoredWidgetDocuments();\n return [];\n };\n\n app.saveStoredWidgetDocuments = function () {\n this.clearStoredWidgetDocuments();\n };\n\n app.clearStoredWidgetDocuments = function () {\n if (!this.chatWidgetStateDocuments) {\n return;\n }\n\n localStorage.removeItem(this.chatWidgetStateDocuments);\n };\n\n app.applyAbsolutePosition = function (element, left, top) {\n if (!element) {\n return;\n }\n\n element.style.left = left + 'px';\n element.style.top = top + 'px';\n element.style.right = 'auto';\n element.style.bottom = 'auto';\n };\n\n app.getWidgetDefaultSize = function () {\n return {\n width: this.widgetDefaultWidth || parsePixelValue(config.widget.defaultWidth) || 380,\n height: this.widgetDefaultHeight || parsePixelValue(config.widget.defaultHeight) || 520\n };\n };\n\n app.getWidgetToggleGap = function () {\n return 8;\n };\n\n app.isWidgetPanelVisible = function () {\n if (!this.widgetContainerElement) {\n return false;\n }\n\n var computed = window.getComputedStyle(this.widgetContainerElement);\n return this.widgetContainerElement.classList.contains('open') && computed.display !== 'none';\n };\n\n app.persistWidgetPanelPosition = function () {\n if (!this.widgetContainerElement || !config.widget.persistLayout) {\n return;\n }\n\n var panelDefaultSize = this.getWidgetDefaultSize();\n var panelPosition = this.getElementPosition(this.widgetContainerElement);\n var panelSize = this.getElementSize(this.widgetContainerElement, panelDefaultSize.width, panelDefaultSize.height);\n var toggleSize = this.getElementSize(this.widgetToggleButtonElement, 52, 52);\n var linkedPosition = this.clampWidgetPosition(\n panelPosition.left + panelSize.width - toggleSize.width,\n panelPosition.top + panelSize.height + this.getWidgetToggleGap(),\n toggleSize.width,\n toggleSize.height);\n\n this.saveStoredWidgetLayout({ position: this.createStoredPosition(linkedPosition.left, linkedPosition.top, toggleSize.width, toggleSize.height) });\n };\n\n app.persistWidgetTogglePosition = function () {\n if (!this.widgetToggleButtonElement || !config.widget.persistLayout) {\n return;\n }\n\n var togglePosition = this.getElementPosition(this.widgetToggleButtonElement);\n var toggleSize = this.getElementSize(this.widgetToggleButtonElement, 52, 52);\n this.saveStoredWidgetLayout({ position: this.createStoredPosition(togglePosition.left, togglePosition.top, toggleSize.width, toggleSize.height) });\n };\n\n app.persistWidgetPanelSize = function () {\n if (!this.widgetContainerElement || !config.widget.enableResizing || !config.widget.persistLayout) {\n return;\n }\n\n var defaultSize = this.getWidgetDefaultSize();\n var currentSize = this.getElementSize(this.widgetContainerElement, defaultSize.width, defaultSize.height);\n\n this.saveStoredWidgetLayout({\n panel: {\n width: Math.abs(currentSize.width - defaultSize.width) <= 1 ? null : currentSize.width,\n height: Math.abs(currentSize.height - defaultSize.height) <= 1 ? null : currentSize.height\n }\n });\n };\n\n app.syncTogglePositionToPanel = function (persistLayout) {\n if (persistLayout === undefined) {\n persistLayout = true;\n }\n\n if (!this.widgetContainerElement || !this.widgetToggleButtonElement) {\n return;\n }\n\n var panelDefaultSize = this.getWidgetDefaultSize();\n var panelSize = this.getElementSize(this.widgetContainerElement, panelDefaultSize.width, panelDefaultSize.height);\n var toggleSize = this.getElementSize(this.widgetToggleButtonElement, 52, 52);\n var panelPosition = this.getElementPosition(this.widgetContainerElement);\n var linkedPosition = this.clampWidgetPosition(\n panelPosition.left + panelSize.width - toggleSize.width,\n panelPosition.top + panelSize.height + this.getWidgetToggleGap(),\n toggleSize.width,\n toggleSize.height);\n\n this.applyAbsolutePosition(this.widgetToggleButtonElement, linkedPosition.left, linkedPosition.top);\n\n if (persistLayout && config.widget.persistLayout) {\n this.persistWidgetTogglePosition();\n }\n };\n\n app.syncPanelPositionToToggle = function (persistLayout) {\n if (persistLayout === undefined) {\n persistLayout = true;\n }\n\n if (!this.widgetContainerElement || !this.widgetToggleButtonElement) {\n return;\n }\n\n var panelDefaultSize = this.getWidgetDefaultSize();\n var panelSize = this.getElementSize(this.widgetContainerElement, panelDefaultSize.width, panelDefaultSize.height);\n var toggleSize = this.getElementSize(this.widgetToggleButtonElement, 52, 52);\n var togglePosition = this.getElementPosition(this.widgetToggleButtonElement);\n var linkedPosition = this.clampWidgetPosition(\n togglePosition.left + toggleSize.width - panelSize.width,\n togglePosition.top - panelSize.height - this.getWidgetToggleGap(),\n panelSize.width,\n panelSize.height);\n\n this.applyAbsolutePosition(this.widgetContainerElement, linkedPosition.left, linkedPosition.top);\n\n if (persistLayout && config.widget.persistLayout) {\n this.persistWidgetPanelPosition();\n }\n };\n\n app.updateWidgetResetSizeButtonVisibility = function () {\n if (!this.widgetResetSizeButtonElement) {\n return;\n }\n\n if (!config.widget.enableResizing || !this.widgetContainerElement) {\n this.widgetResetSizeButtonElement.classList.add('d-none');\n return;\n }\n\n var defaultSize = this.getWidgetDefaultSize();\n var currentSize = this.getElementSize(this.widgetContainerElement, defaultSize.width, defaultSize.height);\n var isResized =\n Math.abs(currentSize.width - defaultSize.width) > 1 ||\n Math.abs(currentSize.height - defaultSize.height) > 1 ||\n !!this.widgetContainerElement.style.width ||\n !!this.widgetContainerElement.style.height;\n\n this.widgetResetSizeButtonElement.classList.toggle('d-none', !isResized);\n };\n\n app.resetWidgetSize = function () {\n if (!this.widgetContainerElement || !config.widget.enableResizing) {\n return;\n }\n\n this.widgetContainerElement.style.removeProperty('width');\n this.widgetContainerElement.style.removeProperty('height');\n this.persistWidgetPanelSize();\n this.constrainWidgetElementsToViewport();\n this.updateWidgetResetSizeButtonVisibility();\n };\n\n app.restoreWidgetLayout = function () {\n var storedLayout = this.getStoredWidgetLayout();\n\n if (this.widgetContainerElement && config.widget.enableResizing) {\n if (Number.isFinite(storedLayout.panel && storedLayout.panel.width)) {\n this.widgetContainerElement.style.width = storedLayout.panel.width + 'px';\n }\n else {\n this.widgetContainerElement.style.removeProperty('width');\n }\n\n if (Number.isFinite(storedLayout.panel && storedLayout.panel.height)) {\n this.widgetContainerElement.style.height = storedLayout.panel.height + 'px';\n }\n else {\n this.widgetContainerElement.style.removeProperty('height');\n }\n }\n\n var toggleSize = this.getElementSize(this.widgetToggleButtonElement, 52, 52);\n var storedTogglePosition = this.resolveStoredPosition(storedLayout.position, toggleSize.width, toggleSize.height);\n if (this.widgetToggleButtonElement && config.widget.enableDragging && storedTogglePosition) {\n this.applyAbsolutePosition(this.widgetToggleButtonElement, storedTogglePosition.left, storedTogglePosition.top);\n this.syncPanelPositionToToggle(false);\n }\n else if (this.widgetToggleButtonElement && config.widget.enableDragging &&\n Number.isFinite(storedLayout.toggle && storedLayout.toggle.left) &&\n Number.isFinite(storedLayout.toggle && storedLayout.toggle.top)) {\n this.applyAbsolutePosition(this.widgetToggleButtonElement, storedLayout.toggle.left, storedLayout.toggle.top);\n this.syncPanelPositionToToggle(false);\n }\n else if (this.widgetContainerElement && config.widget.enableDragging &&\n Number.isFinite(storedLayout.panel && storedLayout.panel.left) &&\n Number.isFinite(storedLayout.panel && storedLayout.panel.top)) {\n this.applyAbsolutePosition(this.widgetContainerElement, storedLayout.panel.left, storedLayout.panel.top);\n this.syncTogglePositionToPanel(false);\n }\n\n this.constrainWidgetElementsToViewport();\n this.updateWidgetResetSizeButtonVisibility();\n };\n\n app.attachDraggableWidgetElement = function (element, handle, layoutKey, suppressClickOnDrag) {\n if (!element || !handle || !config.widget.enableDragging) {\n return;\n }\n\n var activePointerId = null;\n var startX = 0;\n var startY = 0;\n var startLeft = 0;\n var startTop = 0;\n var dragged = false;\n var dragThreshold = 4;\n var interactiveSelector = 'button, a, input, textarea, select, option, label';\n var self = this;\n\n function stopDragging(event) {\n if (activePointerId === null) {\n return;\n }\n\n if (event && event.pointerId !== undefined && event.pointerId !== activePointerId) {\n return;\n }\n\n document.removeEventListener('pointermove', onPointerMove);\n document.removeEventListener('pointerup', stopDragging);\n document.removeEventListener('pointercancel', stopDragging);\n element.classList.remove('ai-chat-widget-dragging');\n activePointerId = null;\n\n if (!dragged) {\n return;\n }\n\n if (layoutKey === 'panel') {\n self.syncTogglePositionToPanel(false);\n self.persistWidgetPanelPosition();\n }\n else if (layoutKey === 'toggle') {\n self.syncPanelPositionToToggle(false);\n self.persistWidgetTogglePosition();\n }\n\n if (config.widget.persistLayout) {\n self.persistWidgetPanelPosition();\n self.persistWidgetTogglePosition();\n }\n\n if (suppressClickOnDrag) {\n element.dataset.dragSuppressClick = 'true';\n window.setTimeout(function () {\n if (element.dataset.dragSuppressClick === 'true') {\n element.dataset.dragSuppressClick = 'false';\n }\n }, 0);\n }\n }\n\n function onPointerMove(event) {\n if (activePointerId === null || event.pointerId !== activePointerId) {\n return;\n }\n\n var deltaX = event.clientX - startX;\n var deltaY = event.clientY - startY;\n\n if (!dragged && Math.hypot(deltaX, deltaY) < dragThreshold) {\n return;\n }\n\n dragged = true;\n\n var defaultSize = self.getWidgetDefaultSize();\n var currentSize = self.getElementSize(\n element,\n layoutKey === 'panel' ? defaultSize.width : 52,\n layoutKey === 'panel' ? defaultSize.height : 52);\n var nextPosition = self.clampWidgetPosition(startLeft + deltaX, startTop + deltaY, currentSize.width, currentSize.height);\n\n self.applyAbsolutePosition(element, nextPosition.left, nextPosition.top);\n\n if (layoutKey === 'panel') {\n self.syncTogglePositionToPanel(false);\n }\n else if (layoutKey === 'toggle') {\n self.syncPanelPositionToToggle(false);\n }\n }\n\n handle.addEventListener('pointerdown', function (event) {\n if (event.button !== 0) {\n return;\n }\n\n if (layoutKey === 'panel' && event.target.closest(interactiveSelector)) {\n return;\n }\n\n var rect = element.getBoundingClientRect();\n startX = event.clientX;\n startY = event.clientY;\n startLeft = rect.left;\n startTop = rect.top;\n dragged = false;\n activePointerId = event.pointerId;\n element.classList.add('ai-chat-widget-dragging');\n\n if (handle.setPointerCapture) {\n handle.setPointerCapture(event.pointerId);\n }\n\n document.addEventListener('pointermove', onPointerMove);\n document.addEventListener('pointerup', stopDragging);\n document.addEventListener('pointercancel', stopDragging);\n event.preventDefault();\n });\n };\n\n app.constrainWidgetElementsToViewport = function () {\n if (this.widgetContainerElement && this.widgetContainerElement.style.left && this.isWidgetPanelVisible()) {\n var panelDefaultSize = this.getWidgetDefaultSize();\n var panelSize = this.getElementSize(this.widgetContainerElement, panelDefaultSize.width, panelDefaultSize.height);\n var panelPosition = this.getElementPosition(this.widgetContainerElement);\n var clampedPanel = this.clampWidgetPosition(panelPosition.left, panelPosition.top, panelSize.width, panelSize.height);\n\n this.applyAbsolutePosition(this.widgetContainerElement, clampedPanel.left, clampedPanel.top);\n this.syncTogglePositionToPanel(false);\n\n if (config.widget.persistLayout) {\n this.persistWidgetPanelPosition();\n this.persistWidgetTogglePosition();\n }\n }\n else if (this.widgetToggleButtonElement && this.widgetToggleButtonElement.style.left) {\n var toggleSize = this.getElementSize(this.widgetToggleButtonElement, 52, 52);\n var togglePosition = this.getElementPosition(this.widgetToggleButtonElement);\n var clampedToggle = this.clampWidgetPosition(togglePosition.left, togglePosition.top, toggleSize.width, toggleSize.height);\n\n this.applyAbsolutePosition(this.widgetToggleButtonElement, clampedToggle.left, clampedToggle.top);\n this.syncPanelPositionToToggle(false);\n\n if (config.widget.persistLayout) {\n this.persistWidgetTogglePosition();\n this.persistWidgetPanelPosition();\n }\n }\n };\n\n app.showChatScreen = function () {\n if (!this.chatHistorySection) {\n return;\n }\n\n this.chatHistorySection.classList.remove('show');\n };\n }\n\n function initialize(app, config) {\n if (!app || app.widgetIsInitialized) {\n return;\n }\n\n if (!config.widget.chatWidgetContainer) {\n console.error('The widget chatWidgetContainer is required.');\n return;\n }\n\n if (!config.widget.chatWidgetStateName) {\n console.error('The widget chatWidgetStateName is required.');\n return;\n }\n\n var chatWidgetContainer = document.querySelector(config.widget.chatWidgetContainer);\n if (!chatWidgetContainer) {\n return;\n }\n\n if (config.widget.chatHistorySection) {\n app.chatHistorySection = document.querySelector(config.widget.chatHistorySection);\n }\n\n app.chatWidgetStateName = config.widget.chatWidgetStateName;\n app.chatWidgetStateSession = config.widget.chatWidgetStateName + 'Session';\n app.chatWidgetStateDocuments = config.widget.chatWidgetStateName + 'Documents';\n app.chatWidgetLayoutKey = config.widget.chatWidgetStateName + 'Layout';\n app.widgetContainerElement = chatWidgetContainer;\n app.widgetToggleButtonElement = config.widget.toggleButtonSelector ? document.querySelector(config.widget.toggleButtonSelector) : null;\n app.widgetResetSizeButtonElement = config.widget.resetSizeButtonSelector ? document.querySelector(config.widget.resetSizeButtonSelector) : null;\n app.widgetDefaultWidth = parsePixelValue(config.widget.defaultWidth) || parsePixelValue(window.getComputedStyle(chatWidgetContainer).width) || 380;\n app.widgetDefaultHeight = parsePixelValue(config.widget.defaultHeight) || parsePixelValue(window.getComputedStyle(chatWidgetContainer).height) || 520;\n app.widgetIsInitialized = true;\n app.clearStoredWidgetDocuments();\n app.documents = [];\n\n if (config.widget.enableResizing) {\n chatWidgetContainer.classList.add('ai-chat-widget-resizable');\n chatWidgetContainer.style.minWidth = (parsePixelValue(config.widget.minWidth) || 320) + 'px';\n chatWidgetContainer.style.minHeight = (parsePixelValue(config.widget.minHeight) || 420) + 'px';\n\n if (typeof ResizeObserver !== 'undefined') {\n app.widgetResizeObserver = new ResizeObserver(function () {\n app.persistWidgetPanelSize();\n app.constrainWidgetElementsToViewport();\n app.updateWidgetResetSizeButtonVisibility();\n });\n\n app.widgetResizeObserver.observe(chatWidgetContainer);\n }\n }\n\n var dragHandleSelector = config.widget.dragHandleSelector || '.ai-chat-widget-header';\n var dragHandle = chatWidgetContainer.querySelector(dragHandleSelector);\n\n if (config.widget.enableDragging && dragHandle) {\n dragHandle.classList.add('ai-chat-widget-drag-handle');\n chatWidgetContainer.classList.add('ai-chat-widget-draggable');\n app.attachDraggableWidgetElement(chatWidgetContainer, dragHandle, 'panel', false);\n }\n\n if (config.widget.enableDragging && app.widgetToggleButtonElement) {\n app.widgetToggleButtonElement.classList.add('ai-chat-widget-draggable');\n app.attachDraggableWidgetElement(app.widgetToggleButtonElement, app.widgetToggleButtonElement, 'toggle', true);\n }\n\n if (app.widgetResetSizeButtonElement) {\n app.widgetResetSizeButtonElement.addEventListener('click', function (event) {\n event.preventDefault();\n app.resetWidgetSize();\n });\n }\n\n app.restoreWidgetLayout();\n\n if (!app.widgetViewportResizeHandler) {\n app.widgetViewportResizeHandler = function () {\n if (config.widget.persistLayout) {\n app.restoreWidgetLayout();\n } else {\n app.constrainWidgetElementsToViewport();\n }\n\n app.updateWidgetResetSizeButtonVisibility();\n };\n\n window.addEventListener('resize', app.widgetViewportResizeHandler);\n }\n\n app.reloadCurrentSession();\n\n if (config.widget.showHistoryButton && app.chatHistorySection) {\n var showHistoryButton = document.querySelector(config.widget.showHistoryButton);\n if (showHistoryButton) {\n showHistoryButton.addEventListener('click', function () {\n app.chatHistorySection.classList.toggle('show');\n });\n }\n\n if (config.widget.closeHistoryButton) {\n var closeHistoryButton = document.querySelector(config.widget.closeHistoryButton);\n if (closeHistoryButton) {\n closeHistoryButton.addEventListener('click', function () {\n app.showChatScreen();\n });\n }\n }\n }\n\n if (config.widget.newChatButton) {\n var newChatButton = document.querySelector(config.widget.newChatButton);\n if (newChatButton) {\n newChatButton.addEventListener('click', function () {\n app.resetSession();\n app.showChatScreen();\n });\n }\n }\n }\n\n function resolveSessionId(app) {\n if (!app || !app.widgetIsInitialized) {\n return null;\n }\n\n return localStorage.getItem(app.chatWidgetStateSession);\n }\n\n function onSessionInitialized(app, sessionId) {\n if (app && app.widgetIsInitialized) {\n localStorage.setItem(app.chatWidgetStateSession, sessionId);\n }\n }\n\n function onSessionReset(app) {\n if (app && app.widgetIsInitialized) {\n localStorage.removeItem(app.chatWidgetStateSession);\n app.clearStoredWidgetDocuments();\n }\n }\n\n function onDocumentsChanged(app, documents) {\n if (app && app.widgetIsInitialized) {\n app.saveStoredWidgetDocuments(documents);\n }\n }\n\n function handleReceiveError(app) {\n if (app && app.widgetIsInitialized && !app.isSessionStarted && !app._attemptedSessionRecovery) {\n app._attemptedSessionRecovery = true;\n localStorage.removeItem(app.chatWidgetStateSession);\n app.clearStoredWidgetDocuments();\n app.startNewSession();\n }\n }\n\n function dispose(app) {\n if (!app) {\n return;\n }\n\n if (app.widgetResizeObserver) {\n app.widgetResizeObserver.disconnect();\n app.widgetResizeObserver = null;\n }\n\n if (app.widgetViewportResizeHandler) {\n window.removeEventListener('resize', app.widgetViewportResizeHandler);\n app.widgetViewportResizeHandler = null;\n }\n }\n\n return {\n attach: attach,\n initialize: initialize,\n onMounted: initialize,\n resolveSessionId: resolveSessionId,\n onSessionInitialized: onSessionInitialized,\n onSessionReset: onSessionReset,\n onDocumentsChanged: onDocumentsChanged,\n handleReceiveError: handleReceiveError,\n dispose: dispose,\n onBeforeUnmount: dispose\n };\n}();\n\nwindow.coreAIChatWidgetManager = window.coreAIChatWidgetManager || function () {\n function getAttributeValue(element, attributeName) {\n var value = element.getAttribute(attributeName);\n return value === null || value === '' ? null : value;\n }\n\n function parseBooleanAttributeValue(value) {\n if (value === null || value === undefined) {\n return null;\n }\n\n if (typeof value === 'boolean') {\n return value;\n }\n\n var normalized = String(value).trim().toLowerCase();\n if (normalized === 'true') {\n return true;\n }\n\n if (normalized === 'false') {\n return false;\n }\n\n return null;\n }\n\n function parseJsonAttribute(element, attributeName, description) {\n var rawValue = getAttributeValue(element, attributeName);\n if (!rawValue) {\n return null;\n }\n\n try {\n return JSON.parse(rawValue);\n }\n catch (error) {\n console.error('Failed to parse ' + description + ' JSON.', error);\n return null;\n }\n }\n\n function buildOptionsFromDataAttributes(element) {\n var widgetContainerSelector = getAttributeValue(element, 'data-coreai-chat-widget-container-selector');\n if (!widgetContainerSelector) {\n return null;\n }\n\n var chatConfig = null;\n if (window.coreAIChatManager && typeof window.coreAIChatManager.buildConfigFromElement === 'function') {\n chatConfig = window.coreAIChatManager.buildConfigFromElement(element, { allowWidgetHost: true });\n }\n\n var profileId = getAttributeValue(element, 'data-coreai-chat-widget-profile-id');\n var profileName = getAttributeValue(element, 'data-coreai-chat-widget-profile-name');\n var profileDisplayText = getAttributeValue(element, 'data-coreai-chat-widget-profile-display-text');\n var profileWelcomeMessage = getAttributeValue(element, 'data-coreai-chat-widget-profile-welcome-message');\n var profileChatMode = getAttributeValue(element, 'data-coreai-chat-widget-profile-chat-mode');\n var profileTtsVoiceName = getAttributeValue(element, 'data-coreai-chat-widget-profile-tts-voice-name');\n var profileMetricsEnabled = parseBooleanAttributeValue(getAttributeValue(element, 'data-coreai-chat-widget-profile-enable-session-metrics'));\n var profileSessionDocuments = parseBooleanAttributeValue(getAttributeValue(element, 'data-coreai-chat-widget-profile-allow-session-documents'));\n var profile = null;\n\n if (profileId || profileName || profileDisplayText || profileWelcomeMessage || profileChatMode || profileTtsVoiceName || profileMetricsEnabled !== null || profileSessionDocuments !== null) {\n profile = {\n id: profileId,\n name: profileName,\n displayText: profileDisplayText,\n welcomeMessage: profileWelcomeMessage,\n chatMode: profileChatMode,\n ttsVoiceName: profileTtsVoiceName,\n enableSessionMetrics: profileMetricsEnabled === true,\n allowSessionDocuments: profileSessionDocuments === true\n };\n }\n\n var enableDragging = parseBooleanAttributeValue(getAttributeValue(element, 'data-coreai-chat-widget-enable-dragging'));\n var enableResizing = parseBooleanAttributeValue(getAttributeValue(element, 'data-coreai-chat-widget-enable-resizing'));\n var persistLayout = parseBooleanAttributeValue(getAttributeValue(element, 'data-coreai-chat-widget-persist-layout'));\n\n return {\n shellSelector: getAttributeValue(element, 'data-coreai-chat-widget-shell-selector'),\n widgetContainerSelector: widgetContainerSelector,\n toggleButtonSelector: getAttributeValue(element, 'data-coreai-chat-widget-toggle-button-selector'),\n closeButtonSelector: getAttributeValue(element, 'data-coreai-chat-widget-close-button-selector'),\n inputSelector: getAttributeValue(element, 'data-coreai-chat-widget-input-selector'),\n messageTemplateSelector: getAttributeValue(element, 'data-coreai-chat-widget-message-template-selector'),\n indicatorTemplateSelector: getAttributeValue(element, 'data-coreai-chat-widget-indicator-template-selector'),\n profile: profile,\n widgetStateName: getAttributeValue(element, 'data-coreai-chat-widget-state-name'),\n openStateValue: getAttributeValue(element, 'data-coreai-chat-widget-open-state-value'),\n closedStateValue: getAttributeValue(element, 'data-coreai-chat-widget-closed-state-value'),\n openIconHtml: getAttributeValue(element, 'data-coreai-chat-widget-open-icon-html'),\n closedIconHtml: getAttributeValue(element, 'data-coreai-chat-widget-closed-icon-html'),\n chatConfig: chatConfig ? Object.assign({}, chatConfig, {\n widget: Object.assign({}, chatConfig.widget || {}, {\n chatWidgetContainer: widgetContainerSelector,\n chatWidgetStateName: getAttributeValue(element, 'data-coreai-chat-widget-state-name'),\n newChatButton: getAttributeValue(element, 'data-coreai-chat-widget-new-chat-button-selector'),\n toggleButtonSelector: getAttributeValue(element, 'data-coreai-chat-widget-toggle-button-selector'),\n resetSizeButtonSelector: getAttributeValue(element, 'data-coreai-chat-widget-reset-size-button-selector'),\n dragHandleSelector: getAttributeValue(element, 'data-coreai-chat-widget-drag-handle-selector'),\n enableDragging: enableDragging === null ? undefined : enableDragging,\n enableResizing: enableResizing === null ? undefined : enableResizing,\n persistLayout: persistLayout === null ? undefined : persistLayout,\n })\n }) : null\n };\n }\n\n function initialize(options) {\n if (!options) {\n return null;\n }\n\n var chatConfig = options.chatConfig;\n if (!chatConfig && options.configElementSelector) {\n var configElement = document.querySelector(options.configElementSelector);\n chatConfig = configElement ? parseJsonAttribute(configElement, 'data-config', 'AI chat widget config') : null;\n }\n\n if (!chatConfig) {\n return null;\n }\n\n if (options.messageTemplateSelector) {\n var messageTemplate = document.querySelector(options.messageTemplateSelector);\n if (messageTemplate) {\n chatConfig.messageTemplate = messageTemplate.innerHTML;\n }\n }\n\n if (options.indicatorTemplateSelector) {\n var indicatorTemplate = document.querySelector(options.indicatorTemplateSelector);\n if (indicatorTemplate) {\n chatConfig.indicatorTemplate = indicatorTemplate.innerHTML;\n }\n }\n\n var shell = document.querySelector(options.shellSelector);\n var widgetContainer = document.querySelector(options.widgetContainerSelector);\n var toggleButton = document.querySelector(options.toggleButtonSelector);\n var closeButton = document.querySelector(options.closeButtonSelector);\n var profileInput = options.inputSelector ? document.querySelector(options.inputSelector) : null;\n var widgetStateName = options.widgetStateName || chatConfig.widget.chatWidgetStateName;\n var widgetOpenStateKey = options.widgetOpenStateKey || (widgetStateName + 'Open');\n var widgetLayoutKey = widgetStateName + 'Layout';\n var openStateValue = options.openStateValue || 'open';\n var closedStateValue = options.closedStateValue || 'closed';\n\n if (profileInput && options.profile && options.profile.id) {\n profileInput.setAttribute('data-profile-id', options.profile.id);\n }\n\n try {\n var storedLayout = localStorage.getItem(widgetLayoutKey);\n var layout = storedLayout ? JSON.parse(storedLayout) || {} : {};\n var position = layout.position || {};\n var panelLayout = layout.panel || {};\n var toggleLeft = Number(position.left);\n var toggleTop = Number(position.top);\n var isOpen = localStorage.getItem(widgetOpenStateKey) === openStateValue;\n var viewportPadding = 8;\n\n if (shell) {\n shell.dataset.deferReveal = isOpen ? 'true' : 'false';\n shell.dataset.initialOpen = isOpen ? 'true' : 'false';\n }\n\n if (widgetContainer && toggleButton) {\n var toggleSize = 52;\n var panelWidth = Number.isFinite(Number(panelLayout.width))\n ? Number(panelLayout.width)\n : Math.round(parseFloat(window.getComputedStyle(widgetContainer).width) || 380);\n var panelHeight = Number.isFinite(Number(panelLayout.height))\n ? Number(panelLayout.height)\n : Math.round(parseFloat(window.getComputedStyle(widgetContainer).height) || 520);\n var maxLeft = Math.max(viewportPadding, window.innerWidth - toggleSize - viewportPadding);\n var maxTop = Math.max(viewportPadding, window.innerHeight - toggleSize - viewportPadding);\n if (Number.isFinite(Number(position.leftRatio))) {\n toggleLeft = viewportPadding + Math.max(0, maxLeft - viewportPadding) * Number(position.leftRatio);\n }\n if (Number.isFinite(Number(position.topRatio))) {\n toggleTop = viewportPadding + Math.max(0, maxTop - viewportPadding) * Number(position.topRatio);\n }\n if (Number.isFinite(toggleLeft) && Number.isFinite(toggleTop)) {\n toggleLeft = Math.round(clampWidgetValue(toggleLeft, viewportPadding, maxLeft));\n toggleTop = Math.round(clampWidgetValue(toggleTop, viewportPadding, maxTop));\n }\n\n if (Number.isFinite(toggleLeft) && Number.isFinite(toggleTop)) {\n toggleButton.style.left = toggleLeft + 'px';\n toggleButton.style.top = toggleTop + 'px';\n toggleButton.style.right = 'auto';\n toggleButton.style.bottom = 'auto';\n\n var toggleGap = 8;\n widgetContainer.style.left = (toggleLeft + toggleSize - panelWidth) + 'px';\n widgetContainer.style.top = (toggleTop - panelHeight - toggleGap) + 'px';\n widgetContainer.style.right = 'auto';\n widgetContainer.style.bottom = 'auto';\n }\n }\n\n if (widgetContainer) {\n widgetContainer.classList.remove('open');\n widgetContainer.style.display = 'none';\n widgetContainer.setAttribute('aria-hidden', 'true');\n }\n\n if (toggleButton) {\n toggleButton.innerHTML = isOpen ? options.openIconHtml : options.closedIconHtml;\n }\n }\n catch (error) {\n console.warn('Failed to restore widget layout before initialization.', error);\n }\n finally {\n if (shell && shell.dataset.deferReveal !== 'true') {\n shell.style.visibility = '';\n }\n }\n\n var widgetApp = window.coreAIChatManager.initialize(chatConfig);\n if (options.applySessionProfilePatch !== false && window.crestAppsAIChat && window.crestAppsAIChat.patchSessionProfileSync) {\n window.crestAppsAIChat.patchSessionProfileSync(widgetApp);\n }\n\n function revealShell() {\n if (!shell) {\n return;\n }\n\n shell.style.visibility = '';\n shell.dataset.deferReveal = 'false';\n }\n\n function syncOpenPanelPosition() {\n if (!widgetApp || typeof widgetApp.syncPanelPositionToToggle !== 'function') {\n return;\n }\n\n widgetApp.syncPanelPositionToToggle(false);\n }\n\n function updateTtsPlaybackButtons() {\n if (!widgetContainer) {\n return;\n }\n\n var buttons = widgetContainer.querySelectorAll('[data-tts-message-index]');\n buttons.forEach(function (button) {\n var buttonIndex = Number(button.getAttribute('data-tts-message-index'));\n var isPlaying = buttonIndex === widgetApp.ttsPlayingMessageIndex;\n button.classList.toggle('tts-playing', isPlaying);\n button.setAttribute('title', isPlaying ? 'Pause audio' : 'Read aloud');\n });\n }\n\n function queueTtsPlaybackButtonUpdate() {\n requestAnimationFrame(updateTtsPlaybackButtons);\n }\n\n function revealShellWhenStable(initialOpen) {\n if (!shell || shell.dataset.deferReveal !== 'true' || !initialOpen) {\n revealShell();\n return;\n }\n\n var hasRevealed = false;\n var resizeObserver = null;\n\n function finalizeReveal() {\n if (hasRevealed) {\n return;\n }\n\n hasRevealed = true;\n\n if (resizeObserver) {\n resizeObserver.disconnect();\n }\n\n requestAnimationFrame(function () {\n syncOpenPanelPosition();\n requestAnimationFrame(function () {\n revealShell();\n });\n });\n }\n\n if (typeof ResizeObserver === 'undefined') {\n window.setTimeout(finalizeReveal, 0);\n return;\n }\n\n var lastWidth = 0;\n var lastHeight = 0;\n var stablePasses = 0;\n\n resizeObserver = new ResizeObserver(function (entries) {\n var entry = entries && entries[0];\n if (!entry) {\n return;\n }\n\n var width = Math.round(entry.contentRect.width);\n var height = Math.round(entry.contentRect.height);\n if (!width || !height) {\n return;\n }\n\n syncOpenPanelPosition();\n\n if (width === lastWidth && height === lastHeight) {\n stablePasses++;\n }\n else {\n lastWidth = width;\n lastHeight = height;\n stablePasses = 0;\n }\n\n if (stablePasses >= 1) {\n finalizeReveal();\n }\n });\n\n resizeObserver.observe(widgetContainer);\n window.setTimeout(finalizeReveal, 150);\n }\n\n function setWidgetOpen(isOpen) {\n if (widgetApp) {\n var isCurrentlyOpen = widgetContainer.classList.contains('open');\n if (isOpen && !isCurrentlyOpen && typeof widgetApp.syncPanelPositionToToggle === 'function') {\n widgetApp.syncPanelPositionToToggle();\n }\n else if (!isOpen && isCurrentlyOpen && typeof widgetApp.syncTogglePositionToPanel === 'function') {\n widgetApp.syncTogglePositionToPanel();\n }\n }\n\n widgetContainer.classList.toggle('open', isOpen);\n widgetContainer.style.display = isOpen ? 'flex' : 'none';\n widgetContainer.setAttribute('aria-hidden', isOpen ? 'false' : 'true');\n toggleButton.innerHTML = isOpen ? options.openIconHtml : options.closedIconHtml;\n localStorage.setItem(widgetOpenStateKey, isOpen ? openStateValue : closedStateValue);\n\n if (isOpen && typeof window.renderPendingCharts === 'function') {\n setTimeout(function () { window.renderPendingCharts(); }, 100);\n }\n }\n\n var initialOpen = shell && shell.dataset.initialOpen === 'true';\n setWidgetOpen(initialOpen);\n revealShellWhenStable(initialOpen);\n\n if (widgetApp && typeof widgetApp.$watch === 'function') {\n widgetApp.$watch('ttsPlayingMessageIndex', function () {\n queueTtsPlaybackButtonUpdate();\n });\n }\n\n queueTtsPlaybackButtonUpdate();\n\n if (toggleButton) {\n toggleButton.addEventListener('click', function () {\n if (toggleButton.dataset.dragSuppressClick === 'true') {\n toggleButton.dataset.dragSuppressClick = 'false';\n return;\n }\n\n setWidgetOpen(!widgetContainer.classList.contains('open'));\n });\n }\n\n if (closeButton) {\n closeButton.addEventListener('click', function () {\n setWidgetOpen(false);\n });\n }\n\n return widgetApp;\n }\n\n function initializeFromElement(element) {\n if (!element || element.dataset.coreAiChatWidgetInitialized === 'true') {\n return element ? element.__coreAIChatWidgetApp || null : null;\n }\n\n var jsonOptions = parseJsonAttribute(element, 'data-coreai-chat-widget-config', 'CoreAI chat widget config');\n var attributeOptions = buildOptionsFromDataAttributes(element);\n if (!jsonOptions && !attributeOptions) {\n return null;\n }\n\n var options = Object.assign({}, jsonOptions || {}, attributeOptions || {});\n\n var widgetApp = initialize(options);\n if (!widgetApp) {\n return null;\n }\n\n element.dataset.coreAiChatWidgetInitialized = 'true';\n element.__coreAIChatWidgetApp = widgetApp;\n\n return widgetApp;\n }\n\n function scanForAutoInitialization(root) {\n if (!root || typeof root.querySelectorAll !== 'function') {\n return;\n }\n\n if (typeof root.matches === 'function' && root.matches('[data-coreai-chat-widget-config],[data-coreai-chat-widget-container-selector]')) {\n initializeFromElement(root);\n }\n\n root.querySelectorAll('[data-coreai-chat-widget-config],[data-coreai-chat-widget-container-selector]').forEach(initializeFromElement);\n }\n\n function startAutoInitialization() {\n scanForAutoInitialization(document);\n\n if (typeof MutationObserver === 'undefined') {\n return;\n }\n\n var observer = new MutationObserver(function (mutations) {\n mutations.forEach(function (mutation) {\n mutation.addedNodes.forEach(function (node) {\n if (node && node.nodeType === 1) {\n scanForAutoInitialization(node);\n }\n });\n });\n });\n\n observer.observe(document.body, {\n childList: true,\n subtree: true,\n });\n }\n\n if (document.readyState === 'loading') {\n document.addEventListener('DOMContentLoaded', startAutoInitialization, { once: true });\n } else {\n startAutoInitialization();\n }\n\n return {\n initialize: initialize,\n initializeFromElement: initializeFromElement,\n };\n}();\n"]} diff --git a/src/Resources/CrestApps.AI.Resources/wwwroot/scripts/ai-chat.js b/src/Resources/CrestApps.AI.Resources/wwwroot/scripts/ai-chat.js index 32618d60..d8199eac 100644 --- a/src/Resources/CrestApps.AI.Resources/wwwroot/scripts/ai-chat.js +++ b/src/Resources/CrestApps.AI.Resources/wwwroot/scripts/ai-chat.js @@ -1355,8 +1355,6 @@ window.coreAIChatManager = function () { console.info("SignalR: reconnected."); if (_this3.isSessionStarted) { _this3.reloadCurrentSession(); - } else if (config.autoCreateSession) { - _this3.startNewSession(); } }); _this3.connection.onclose(function (error) { @@ -2311,12 +2309,7 @@ window.coreAIChatManager = function () { this.sessionRating = null; this.messages = []; this.documents = []; - if (!config.autoCreateSession) { - this.showPlaceholder(); - } - if (config.autoCreateSession) { - this.startNewSession(); - } + this.showPlaceholder(); if (widgetBehavior && typeof widgetBehavior.onSessionReset === 'function') { widgetBehavior.onSessionReset(this, config); } @@ -2421,8 +2414,6 @@ window.coreAIChatManager = function () { var sessionId = this.getSessionId(); if (!hasWidgetConfig && sessionId) { this.loadSession(sessionId); - } else if (this.isOrchestratorAvailable() && config.autoCreateSession && !hasWidgetConfig && !sessionId) { - this.startNewSession(); } // Initialize document bar if enabled. @@ -2904,7 +2895,6 @@ window.coreAIChatManager = function () { metricsEnabled: 'data-coreai-chat-metrics-enabled', textToSpeechEnabled: 'data-coreai-chat-text-to-speech-enabled', sessionDocumentsEnabled: 'data-coreai-chat-session-documents-enabled', - autoCreateSession: 'data-coreai-chat-auto-create-session', singleResponseMode: 'data-coreai-chat-single-response-mode' }; Object.keys(booleanAttributes).forEach(function (key) { diff --git a/src/Resources/CrestApps.AI.Resources/wwwroot/scripts/ai-chat.js.map b/src/Resources/CrestApps.AI.Resources/wwwroot/scripts/ai-chat.js.map index 157db5d6..e68dbf21 100644 --- a/src/Resources/CrestApps.AI.Resources/wwwroot/scripts/ai-chat.js.map +++ b/src/Resources/CrestApps.AI.Resources/wwwroot/scripts/ai-chat.js.map @@ -1 +1 @@ -{"version":3,"sources":["ai-chat.js"],"names":["e","t","r","Symbol","n","iterator","o","toStringTag","i","c","prototype","Generator","u","Object","create","_regeneratorDefine2","f","p","y","G","v","a","d","bind","length","l","TypeError","call","done","value","GeneratorFunction","GeneratorFunctionPrototype","getPrototypeOf","setPrototypeOf","__proto__","displayName","_regenerator","w","m","defineProperty","_regeneratorDefine","_invoke","enumerable","configurable","writable","asyncGeneratorStep","Promise","resolve","then","_asyncToGenerator","arguments","apply","_next","_throw","_toConsumableArray","_arrayWithoutHoles","_iterableToArray","_unsupportedIterableToArray","_nonIterableSpread","Array","from","isArray","_arrayLikeToArray","_objectWithoutProperties","_objectWithoutPropertiesLoose","getOwnPropertySymbols","indexOf","propertyIsEnumerable","hasOwnProperty","_createForOfIteratorHelper","_n","F","s","next","_slicedToArray","_arrayWithHoles","_iterableToArrayLimit","_nonIterableRest","toString","slice","constructor","name","test","push","_typeof","window","coreAIChatManager","defaultConfig","generatedImageAltText","generatedImageMaxWidth","downloadImageTitle","downloadChartTitle","downloadChartButtonText","userLabel","assistantLabel","thumbsUpTitle","thumbsDownTitle","copyTitle","copiedTitle","codeCopiedText","copyResetDelayMs","widget","chatWidgetContainer","chatWidgetStateName","chatHistorySection","showHistoryButton","closeHistoryButton","newChatButton","toggleButtonSelector","resetSizeButtonSelector","dragHandleSelector","enableDragging","enableResizing","persistLayout","defaultWidth","defaultHeight","minWidth","minHeight","messageTemplate","indicatorTemplate","sanitizeUrl","url","trimmed","trim","escapeHtmlEntities","text","span","document","createElement","textContent","innerHTML","containsFontAwesomePlaceholders","root","nodeType","selector","matches","querySelector","refreshFontAwesomeIcons","fontAwesome","FontAwesome","dom","i2svg","node","observeFontAwesomeIcons","MutationObserver","observer","mutations","forEach","mutation","addedNodes","observe","childList","subtree","parsePixelValue","Number","isFinite","parsed","parseFloat","clamp","min","max","Math","normalizeReference","reference","_ref","_normalized$index","_ref2","_normalized$text","_ref3","_normalized$title","_ref4","_normalized$link","_ref5","_normalized$reference","_normalized$isGenerat","normalized","assign","index","Index","Text","title","Title","link","Link","referenceType","ReferenceType","isGenerated","IsGenerated","isDownloadCitationReference","toLowerCase","normalizeReferences","references","_i","_Object$entries","entries","_normalizeReference","_Object$entries$_i","key","getCitationLabel","buildCitationDisplay","content","processedContent","messageReferences","referenceEntries","citations","citedRefs","filter","_ref6","_ref7","includes","generatedRefs","_ref8","_ref9","sort","_ref0","_ref1","_ref10","_ref11","b","_ref12","_ref13","_ref14","_ref15","displayIndex","_iterator","_step","_step$value","placeholder","concat","replaceAll","referenceKey","label","isDownload","err","_i2","_citations","citation","_iterator2","_step2","_step2$value","map","_ref16","_excluded","buildCopyContent","copyContent","_iterator3","_step3","_iterator4","_step4","trimEnd","updateMessagePresentation","message","rawContent","citationDisplay","displayContent","citationReferences","htmlContent","parseMarkdownContent","renderer","marked","Renderer","data","href","code","lang","highlighted","hljs","getLanguage","highlight","language","_","highlightAuto","langDisplay","image","src","alt","maxWidth","chartCounter","_pendingCharts","__chartConfigs","createChartHtml","chartId","use","extensions","level","start","idx","undefined","tokenizer","extracted","tryExtractChartMarker","startIndex","type","raw","substring","endIndex","json","token","config","jsonStart","depth","inString","escape","ch","jsonEnd","closeBracketIndex","renderChartsInMessage","charts","requestAnimationFrame","_iterator5","_step5","renderChartOnCanvas","canvas","getElementById","Chart","console","warn","offsetParent","_cfg$options","_cfg$options2","_cfg$options2$aspectR","_chartInstance","destroy","cfg","JSON","parse","options","responsive","maintainAspectRatio","aspectRatio","error","renderPendingCharts","configs","_i3","_Object$keys","keys","html","DOMPurify","sanitize","ADD_TAGS","ADD_ATTR","compactObject","source","fromEntries","_ref17","_ref18","resolveIndicatorTemplate","template","encodedAssistantLabel","replace","initialize","instanceConfig","normalizedInstanceConfig","normalizedWidgetConfig","hasWidgetConfig","widgetBehavior","coreAIChatWidgetBehavior","signalRHubUrl","appElementSelector","chatContainerElementSelector","inputElementSelector","sendButtonElementSelector","appDefinition","inputElement","buttonElement","chatContainer","isSessionStarted","isPlaceholderVisible","isStreaming","isNavigatingAway","autoScroll","stream","messages","notifications","prompt","documents","existingDocuments","isUploading","isDocumentOperationPending","documentOperationQueue","uploadErrors","isDragOver","documentBar","metricsEnabled","isRecording","mediaRecorder","preRecordingPrompt","micButton","speechToTextEnabled","chatMode","textToSpeechEnabled","ttsVoiceName","audioChunks","audioPlayQueue","isPlayingAudio","currentAudioElement","currentAudioUrl","ttsButton","ttsPlayingMessageIndex","ttsAudioCache","ttsInstanceId","random","singleResponseMode","conversationModeEnabled","conversationButton","isConversationMode","notificationDismissTimers","pendingSessionPromise","pendingSessionResolver","pendingSessionRejector","pendingSessionTimeoutId","copiedMessageIndex","copyResetTimeoutId","activeCopyButton","computed","lastAssistantIndex","role","methods","handleBeforeUnload","handleDragOver","sessionDocumentsEnabled","preventDefault","stopPropagation","inputArea","closest","classList","add","handleDragLeave","remove","handleDrop","dataTransfer","files","uploadFiles","triggerFileInput","fileInput","click","handleFileInputChange","target","queueDocumentOperation","operation","self","previousOperation","nextOperation","_callee","_context","_this","_callee3","filesToUpload","_context3","uploadDocumentUrl","_callee2","sessionId","profileId","formData","response","errorText","uploadError","result","_t","_t2","_context2","getSessionId","getProfileId","ensureSessionForDocuments","fileName","renderDocumentBar","FormData","append","fetch","method","body","ok","extractReadableErrorMessage","initializeSession","uploaded","failed","reloadCurrentSession","removeDocument","doc","_this2","_callee5","_context5","removeDocumentUrl","_callee4","removeError","_t3","_context4","headers","stringify","itemId","documentId","splice","status","formatFileSize","bytes","toFixed","escapeHtml","failedItem","failedName","errorMsg","supportedExtensionsText","replaceChildren","RETURN_DOM_FRAGMENT","closeButtons","querySelectorAll","j","addEventListener","docToRemove","parseInt","getAttribute","errorCloseButtons","addBtn","div","fallbackMessage","startsWith","detail","normalizeAssistantAppearance","appearance","icon","cssClass","disableStreamingAnimation","getAssistantLabel","getAssistantRoleClasses","classes","getAssistantIconClasses","shouldAnimateAssistantIcon","getAssistantIcon","startConnection","_this3","_callee6","_t4","_context6","connection","signalR","HubConnectionBuilder","withUrl","withAutomaticReconnect","build","serverTimeoutInMilliseconds","keepAliveIntervalInMilliseconds","on","_data$messages","msg","addMessage","$nextTick","refreshAllFeedbackIcons","initialPrompt","sendMessage","stopRecording","handleReceiveError","messageId","userRating","find","id","isFinal","_conversationPartialTranscript","escaped","_conversationPartialMessage","hidePlaceholder","isPartial","scrollToBottom","_audioInputSent","dispatchEvent","Event","stopAudio","_conversationAssistantMessage","oldMsg","responseId","hideTypingIndicator","msgIndex","newMessage","base64Audio","contentType","binaryString","atob","Uint8Array","charCodeAt","playCollectedAudio","notification","receiveNotification","updateNotification","notificationType","removeNotification","onreconnecting","onreconnected","info","autoCreateSession","startNewSession","onclose","addMessageInternal","_this4","fireEvent","CustomEvent","_this5","_message$rawContent","addMessages","_this6","showPlaceholder","isOrchestratorAvailable","applyOrchestratorAvailability","unavailableMessage","orchestratorUnavailableMessage","disabled","micButtonElement","style","display","conversationButtonElement","event","isIndicator","trimmedPrompt","streamMessage","startRecording","_this7","navigator","mediaDevices","getUserMedia","audio","echoCancellation","noiseSuppression","autoGainControl","mimeType","MediaRecorder","isTypeSupported","audioBitsPerSecond","subject","Subject","pendingChunk","size","_callee7","uint8Array","base64","_context7","arrayBuffer","reduce","str","byte","String","fromCharCode","btoa","getTracks","track","stop","complete","documentElement","send","updateMicButton","toggleRecording","sessionProfileId","_this8","dispose","streamingStarted","showTypingIndicator","lastResponseId","messageIndex","currentSessionId","subscribe","chunk","_i4","_Object$entries2","_normalizeReference2","_Object$entries2$_i","_this8$stream","processReferences","streamingFinished","synthesizeSpeech","_this8$stream2","getServiceDownMessage","_this9","_ref23","_message$rawContent2","stopIcon","setAttribute","startIcon","removeAttribute","focus","icons","handleExternalTtsStop","_e$detail","sourceId","updateTtsPlaybackButtons","_this0","buttons","button","buttonIndex","isPlaying","toggle","updateCopyButtons","_this1","isCopied","iconHtml","setCopyButtonState","cacheIndex","_this10","_ttsCacheIndex","invoke","toggleMessageTts","_this11","playAudioBlob","_this12","totalLength","sum","combined","offset","_iterator6","_step6","set","blob","Blob","_this13","URL","createObjectURL","Audio","revokeObjectURL","playNextInQueue","play","_this14","nextBlob","shift","conversationModeOnAudioEnded","_this15","pause","currentTime","toggleConversationMode","stopConversationMode","startConversationMode","_this16","updateConversationButton","_conversationSubject","_conversationStream","AudioCtx","AudioContext","webkitAudioContext","_conversationAudioCtx","_conversationAnalyser","createAnalyser","fftSize","micSource","createMediaStreamSource","connect","analyser","interruptVolumeThreshold","freqData","frequencyBinCount","getByteFrequencyData","k","avg","_callee8","_context8","close","dismissible","autoDismissMs","endHtml","blur","startHtml","conversationModeSendPrompt","generatePrompt","element","templateProfileId","createSessionUrl","baseUrl","param","fullUrl","location","origin","searchParams","originalLength","removedCount","_this17","clearNotificationDismiss","existingIndex","findIndex","scheduleNotificationDismiss","_this18","setTimeout","timerId","clearTimeout","dismissNotification","handleNotificationAction","actionName","_this19","scrollTop","scrollHeight","clientHeight","handleUserInput","setSessionId","resetSession","rejectPendingSessionRequest","sessionRating","onSessionReset","requestNewSession","_this20","_callee9","_context9","_this21","reject","resolvePendingSessionRequest","clearPendingSessionRequest","initializeApp","_this22","placeholderElementSelector","loadSession","documentBarSelector","className","multiple","allowedExtensions","accept","parentElement","appendChild","threshold","atBottom","shiftKey","lastMsg","pop","promptGenerators","getElementsByClassName","chatSessions","showChatScreen","initialMessages","btn","block","codeEl","clipboard","writeText","copiedText","micButtonElementSelector","conversationButtonElementSelector","force","onSessionInitialized","resolveSessionId","clearCopiedMessageState","copyResponse","_ref25","_message$copyContent","_event$target","_event$target$closest","_this23","currentTarget","updateFeedbackIcons","container","upBtn","downBtn","upClass","upIcon","fontSize","downClass","downIcon","containers","$el","msgId","rateMessage","isPositive","newRating","feedbackContainer","btnClass","offsetWidth","onEnd","removeEventListener","watch","handler","onDocumentsChanged","deep","_this24","active","mounted","_this25","_callee0","isInitialized","_context0","onMounted","fontAwesomeObserver","beforeUnmount","disconnect","onBeforeUnmount","app","Vue","createApp","mount","attach","autoInitializeSelector","getAttributeValue","attributeName","parseBooleanAttributeValue","parseJsonAttribute","description","rawValue","buildConfigFromDataAttributes","_parseJsonAttribute","_parseJsonAttribute2","settings","hasAttribute","allowWidgetHost","booleanAttributes","buildConfigFromElement","jsonConfig","attributeConfig","initializeFromElement","dataset","coreAiChatInitialized","__coreAIChatApp","scanForAutoInitialization","startAutoInitialization","readyState","once","download","toDataURL","img","res","removeChild"],"mappings":"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","file":"ai-chat.js","sourcesContent":["window.coreAIChatManager = function () {\n\n // Defaults (can be overridden by instanceConfig)\n var defaultConfig = {\n // UI defaults for generated media\n generatedImageAltText: 'Generated Image',\n generatedImageMaxWidth: 400,\n downloadImageTitle: 'Download image',\n downloadChartTitle: 'Download chart as image',\n downloadChartButtonText: 'Download',\n userLabel: 'You',\n assistantLabel: 'Assistant',\n thumbsUpTitle: 'Thumbs up',\n thumbsDownTitle: 'Thumbs down',\n copyTitle: 'Click here to copy response to clipboard.',\n copiedTitle: 'Response copied to clipboard.',\n codeCopiedText: 'Copied!',\n copyResetDelayMs: 2000,\n widget: {\n chatWidgetContainer: null,\n chatWidgetStateName: null,\n chatHistorySection: null,\n showHistoryButton: null,\n closeHistoryButton: null,\n newChatButton: null,\n toggleButtonSelector: null,\n resetSizeButtonSelector: null,\n dragHandleSelector: '.ai-chat-widget-header',\n enableDragging: true,\n enableResizing: true,\n persistLayout: true,\n defaultWidth: null,\n defaultHeight: null,\n minWidth: 320,\n minHeight: 420\n },\n messageTemplate: `\n
\n
\n
\n
\n {{ userLabel }}\n
\n
\n
\n \n {{ getAssistantLabel(message) }}\n
\n
\n
\n

{{ message.title }}

\n
\n
    \n
  1. \n {{ citation.label }}\n {{ citation.label }}\n
  2. \n
\n \n \n \n \n \n
\n
\n
\n
\n
\n \n {{ notification.content }}\n \n
\n
\n \n
\n
\n
\n `,\n indicatorTemplate: `\n
\n
\n \n Assistant\n
\n
\n `\n };\n\n // Sanitize URLs to prevent javascript: protocol injection.\n function sanitizeUrl(url) {\n if (!url) return '';\n var trimmed = url.trim();\n if (/^javascript:/i.test(trimmed) || /^vbscript:/i.test(trimmed) || /^data:text\\/html/i.test(trimmed)) {\n return '';\n }\n return url;\n }\n\n // Safely HTML-encode a string using the DOM (avoids regex-based HTML filtering).\n function escapeHtmlEntities(text) {\n var span = document.createElement('span');\n span.textContent = text;\n return span.innerHTML;\n }\n\n function containsFontAwesomePlaceholders(root) {\n if (!root || root.nodeType !== 1) {\n return false;\n }\n\n var selector = 'i[class*=\"fa-\"],i.fa,i.fas,i.far,i.fab';\n if (typeof root.matches === 'function' && root.matches(selector)) {\n return true;\n }\n\n return typeof root.querySelector === 'function' && !!root.querySelector(selector);\n }\n\n function refreshFontAwesomeIcons(root) {\n var fontAwesome = window.FontAwesome;\n if (!containsFontAwesomePlaceholders(root) || !fontAwesome || !fontAwesome.dom || typeof fontAwesome.dom.i2svg !== 'function') {\n return;\n }\n\n fontAwesome.dom.i2svg({ node: root });\n }\n\n function observeFontAwesomeIcons(root) {\n if (!root || typeof MutationObserver === 'undefined') {\n return null;\n }\n\n var observer = new MutationObserver(function (mutations) {\n mutations.forEach(function (mutation) {\n mutation.addedNodes.forEach(function (node) {\n refreshFontAwesomeIcons(node);\n });\n });\n });\n\n observer.observe(root, {\n childList: true,\n subtree: true\n });\n\n return observer;\n }\n\n function parsePixelValue(value) {\n if (typeof value === 'number' && Number.isFinite(value)) {\n return value;\n }\n\n if (typeof value !== 'string') {\n return null;\n }\n\n var parsed = parseFloat(value);\n return Number.isFinite(parsed) ? parsed : null;\n }\n\n function clamp(value, min, max) {\n return Math.min(Math.max(value, min), max);\n }\n\n function normalizeReference(reference) {\n if (!reference || typeof reference !== 'object') {\n return null;\n }\n\n const normalized = Object.assign({}, reference);\n normalized.index = normalized.index ?? normalized.Index ?? 0;\n normalized.text = normalized.text ?? normalized.Text ?? null;\n normalized.title = normalized.title ?? normalized.Title ?? null;\n normalized.link = sanitizeUrl(normalized.link ?? normalized.Link ?? null);\n normalized.referenceType = normalized.referenceType ?? normalized.ReferenceType ?? null;\n normalized.isGenerated = (normalized.isGenerated ?? normalized.IsGenerated) === true;\n\n return normalized;\n }\n\n function isDownloadCitationReference(reference) {\n if (!reference || typeof reference !== 'object') {\n return false;\n }\n\n if (typeof reference.referenceType === 'string' && reference.referenceType.toLowerCase() === 'document') {\n return true;\n }\n\n if (typeof reference.link === 'string' && /\\/ai\\/documents\\/.+\\/download(?:$|\\?)/i.test(reference.link)) {\n return true;\n }\n\n return false;\n }\n\n function normalizeReferences(references) {\n if (!references || typeof references !== 'object') {\n return {};\n }\n\n const normalized = {};\n\n for (const [key, value] of Object.entries(references)) {\n normalized[key] = normalizeReference(value) ?? {};\n }\n\n return normalized;\n }\n\n function getCitationLabel(reference, key) {\n return reference.title || reference.text || key;\n }\n\n function buildCitationDisplay(content, references) {\n let processedContent = (content || '').trim();\n const messageReferences = normalizeReferences(references);\n const referenceEntries = Object.entries(messageReferences);\n\n if (!referenceEntries.length) {\n return { content: processedContent, citations: [] };\n }\n\n const citedRefs = referenceEntries.filter(([key]) => processedContent.includes(key));\n const generatedRefs = referenceEntries.filter(([key, value]) => value.isGenerated && !processedContent.includes(key));\n\n if (!citedRefs.length && !generatedRefs.length) {\n return { content: processedContent, citations: [] };\n }\n\n citedRefs.sort(([, a], [, b]) => a.index - b.index);\n generatedRefs.sort(([, a], [, b]) => a.index - b.index);\n\n const citations = [];\n let displayIndex = 1;\n\n for (const [key, value] of citedRefs) {\n const placeholder = `__CITE_${displayIndex}_${value.index || displayIndex}__`;\n processedContent = processedContent.replaceAll(key, placeholder);\n citations.push({\n referenceKey: key,\n displayIndex: displayIndex,\n label: getCitationLabel(value, key),\n link: value.link || null,\n isDownload: isDownloadCitationReference(value),\n placeholder: placeholder,\n });\n\n displayIndex++;\n }\n\n for (const citation of citations) {\n processedContent = processedContent.replaceAll(citation.placeholder, `${citation.displayIndex}`);\n }\n\n processedContent = processedContent.replaceAll('', ',');\n\n // Generated files (such as exported tabular data) are always offered as a download even when\n // the model does not cite them inline, so the user never loses access to the produced file.\n for (const [key, value] of generatedRefs) {\n citations.push({\n referenceKey: key,\n displayIndex: displayIndex,\n label: getCitationLabel(value, key),\n link: value.link || null,\n isDownload: true,\n placeholder: null,\n });\n\n displayIndex++;\n }\n\n return {\n content: processedContent,\n citations: citations.map(({ placeholder, ...citation }) => citation),\n };\n }\n\n function buildCopyContent(content, citations) {\n let copyContent = (content || '').trim();\n\n if (!copyContent || !Array.isArray(citations) || citations.length === 0) {\n return copyContent;\n }\n\n for (const citation of citations) {\n copyContent = copyContent.replaceAll(citation.referenceKey, `[${citation.displayIndex}]`);\n }\n\n copyContent += '\\n\\nReferences:\\n';\n\n for (const citation of citations) {\n copyContent += `${citation.displayIndex}. ${citation.label}`;\n\n if (citation.link) {\n copyContent += ` - ${citation.link}`;\n }\n\n copyContent += '\\n';\n }\n\n return copyContent.trimEnd();\n }\n\n function updateMessagePresentation(message, references) {\n const messageReferences = normalizeReferences(references ?? message.references);\n const rawContent = typeof message.rawContent === 'string'\n ? message.rawContent\n : typeof message.content === 'string'\n ? message.content\n : '';\n const citationDisplay = buildCitationDisplay(rawContent, messageReferences);\n\n message.rawContent = rawContent;\n message.content = rawContent;\n message.displayContent = citationDisplay.content;\n message.references = messageReferences;\n message.citationReferences = citationDisplay.citations;\n message.copyContent = buildCopyContent(rawContent, citationDisplay.citations);\n message.htmlContent = parseMarkdownContent(citationDisplay.content, message);\n\n return message;\n }\n\n const renderer = new marked.Renderer();\n\n // Modify the link rendering to open in a new tab\n renderer.link = function (data) {\n var href = sanitizeUrl(data.href);\n if (!href) return data.text || '';\n return `${data.text}`;\n };\n\n // Custom code block renderer with highlight.js integration and copy button.\n renderer.code = function (data) {\n var code = data.text || '';\n var lang = (data.lang || '').trim();\n var highlighted = code;\n\n if (typeof hljs !== 'undefined') {\n if (lang && hljs.getLanguage(lang)) {\n try {\n highlighted = hljs.highlight(code, { language: lang }).value;\n } catch (_) { }\n } else {\n try {\n highlighted = hljs.highlightAuto(code).value;\n } catch (_) { }\n }\n } else {\n highlighted = escapeHtmlEntities(code);\n }\n\n var langDisplay = lang ? escapeHtmlEntities(lang) : 'code';\n return `
${langDisplay}
${highlighted}
`;\n };\n\n // Custom image renderer for generated images with thumbnail styling and download button.\n // Handles both URL and data-URI sources (data URIs are converted to blobs for download).\n renderer.image = function (data) {\n const src = sanitizeUrl(data.href);\n if (!src) return '';\n const alt = data.text || defaultConfig.generatedImageAltText;\n const maxWidth = defaultConfig.generatedImageMaxWidth;\n return `
\n \"${alt}\"\n
\n \n \n \n
\n
`;\n };\n\n // Chart counter for unique IDs\n let chartCounter = 0;\n\n // Collector for charts discovered during marked parsing.\n let _pendingCharts = [];\n\n // Global chart config map: any page (e.g., Chat Interactions) that uses\n // the shared marked instance can call window.renderPendingCharts() after\n // its DOM update to render charts it didn't create itself.\n window.__chartConfigs = window.__chartConfigs || {};\n\n function createChartHtml(chartId) {\n return `
`\n + ``\n + `
`\n + `
`\n + ``\n + `
`;\n }\n\n // Register [chart:{...json...}] as a native marked block extension so the\n // markdown parser handles chart markers inline with surrounding text.\n marked.use({\n extensions: [{\n name: 'chart',\n level: 'block',\n start(src) {\n const idx = src.indexOf('[chart:');\n return idx >= 0 ? idx : undefined;\n },\n tokenizer(src) {\n const extracted = tryExtractChartMarker(src);\n if (!extracted || extracted.startIndex !== 0) {\n return undefined;\n }\n\n const chartId = `chat_chart_${++chartCounter}`;\n\n return {\n type: 'chart',\n raw: src.substring(0, extracted.endIndex),\n chartId: chartId,\n json: extracted.json,\n };\n },\n renderer(token) {\n _pendingCharts.push({ chartId: token.chartId, config: token.json });\n window.__chartConfigs[token.chartId] = token.json;\n return createChartHtml(token.chartId);\n }\n }]\n });\n\n // Extract a [chart:{...json...}] marker. This avoids regex issues with nested brackets.\n function tryExtractChartMarker(text) {\n const token = '[chart:';\n const start = text.indexOf(token);\n if (start < 0) {\n return null;\n }\n\n // Find JSON object boundary by balancing braces\n const jsonStart = start + token.length;\n let i = jsonStart;\n while (i < text.length && (text[i] === ' ' || text[i] === '\\n' || text[i] === '\\r' || text[i] === '\\t')) {\n i++;\n }\n\n if (i >= text.length || text[i] !== '{') {\n return null;\n }\n\n let depth = 0;\n let inString = false;\n let escape = false;\n\n for (; i < text.length; i++) {\n const ch = text[i];\n\n if (inString) {\n if (escape) {\n escape = false;\n continue;\n }\n if (ch === '\\\\') {\n escape = true;\n continue;\n }\n if (ch === '\"') {\n inString = false;\n }\n continue;\n }\n\n if (ch === '\"') {\n inString = true;\n continue;\n }\n\n if (ch === '{') {\n depth++;\n } else if (ch === '}') {\n depth--;\n if (depth === 0) {\n const jsonEnd = i;\n // Expect closing bracket after JSON\n const closeBracketIndex = text.indexOf(']', jsonEnd + 1);\n if (closeBracketIndex < 0) {\n return null;\n }\n\n const json = text.substring(jsonStart, jsonEnd + 1).trim();\n return {\n startIndex: start,\n endIndex: closeBracketIndex + 1,\n json: json\n };\n }\n }\n }\n\n return null;\n }\n\n function renderChartsInMessage(message) {\n if (!message || !message._pendingCharts || !message._pendingCharts.length) {\n return;\n }\n\n // Copy and clear pending charts immediately to prevent duplicate renders.\n const charts = [...message._pendingCharts];\n message._pendingCharts = [];\n\n // Defer to requestAnimationFrame so the browser has fully laid out the\n // canvas elements before Chart.js reads their dimensions.\n requestAnimationFrame(() => {\n for (const c of charts) {\n renderChartOnCanvas(c.chartId, c.config);\n }\n });\n }\n\n function renderChartOnCanvas(chartId, config) {\n const canvas = document.getElementById(chartId);\n if (!canvas) {\n return false;\n }\n\n if (typeof Chart === 'undefined') {\n console.warn('Chart.js is not loaded. To render interactive charts, include the Chart.js library on the page (e.g., ).');\n return false;\n }\n\n // When the canvas is inside a hidden container (e.g., a widget panel with\n // display:none), it has zero dimensions and Chart.js cannot render correctly.\n // Keep the config in __chartConfigs so renderPendingCharts() can retry later\n // once the container becomes visible.\n if (canvas.offsetParent === null) {\n window.__chartConfigs[chartId] = config;\n return false;\n }\n\n try {\n if (canvas._chartInstance) {\n canvas._chartInstance.destroy();\n }\n\n const cfg = typeof config === 'string' ? JSON.parse(config) : config;\n cfg.options ??= {};\n cfg.options.responsive = true;\n cfg.options.maintainAspectRatio = true;\n cfg.options.aspectRatio ??= 4 / 3;\n\n canvas._chartInstance = new Chart(canvas, cfg);\n delete window.__chartConfigs[chartId];\n return true;\n } catch (e) {\n console.error('Error creating chart:', e);\n return false;\n }\n }\n\n // Global function: renders any chart canvases whose configs are in the\n // global __chartConfigs map. Called by pages (e.g., Chat Interactions)\n // that share the marked instance but have their own rendering pipeline.\n window.renderPendingCharts = function () {\n if (typeof Chart === 'undefined') {\n return;\n }\n\n const configs = window.__chartConfigs;\n if (!configs) {\n return;\n }\n\n requestAnimationFrame(() => {\n for (const chartId of Object.keys(configs)) {\n renderChartOnCanvas(chartId, configs[chartId]);\n }\n });\n };\n\n // Parse markdown content via marked (which natively handles [chart:...] markers\n // through the registered extension) and collect pending chart configs for later\n // Chart.js rendering.\n function parseMarkdownContent(content, message) {\n _pendingCharts = [];\n const html = marked.parse(content, { renderer });\n message._pendingCharts = _pendingCharts.length > 0 ? [..._pendingCharts] : [];\n return DOMPurify.sanitize(html, { ADD_TAGS: ['canvas'], ADD_ATTR: ['target'] });\n }\n\n function compactObject(source) {\n if (!source || typeof source !== 'object') {\n return {};\n }\n\n return Object.fromEntries(\n Object.entries(source).filter(([, value]) => value !== undefined)\n );\n }\n\n function resolveIndicatorTemplate(template, assistantLabel) {\n if (!template) {\n return template;\n }\n\n const encodedAssistantLabel = escapeHtmlEntities(assistantLabel || 'Assistant');\n return template.replace(/\\{\\{\\s*assistantLabel\\s*\\}\\}/g, encodedAssistantLabel);\n }\n\n const initialize = (instanceConfig) => {\n const normalizedInstanceConfig = compactObject(instanceConfig);\n const normalizedWidgetConfig = compactObject(normalizedInstanceConfig.widget);\n const config = Object.assign({}, defaultConfig, normalizedInstanceConfig);\n config.widget = Object.assign({}, defaultConfig.widget || {}, normalizedWidgetConfig);\n config.indicatorTemplate = resolveIndicatorTemplate(config.indicatorTemplate, config.assistantLabel);\n const hasWidgetConfig = !!(normalizedWidgetConfig.chatWidgetContainer && normalizedWidgetConfig.chatWidgetStateName);\n const widgetBehavior = window.coreAIChatWidgetBehavior || null;\n // Keep defaultConfig in sync so renderers use overridden values\n defaultConfig = config;\n\n if (!config.signalRHubUrl) {\n console.error('The signalRHubUrl is required.');\n return;\n }\n\n if (!config.appElementSelector) {\n console.error('The appElementSelector is required.');\n return;\n }\n\n if (!config.chatContainerElementSelector) {\n console.error('The chatContainerElementSelector is required.');\n return;\n }\n\n if (!config.inputElementSelector) {\n console.error('The inputElementSelector is required.');\n return;\n }\n\n if (!config.sendButtonElementSelector) {\n console.error('The sendButtonElementSelector is required.');\n return;\n }\n\n const appDefinition = {\n data() {\n return {\n inputElement: null,\n buttonElement: null,\n chatContainer: null,\n placeholder: null,\n isSessionStarted: false,\n isPlaceholderVisible: true,\n isStreaming: false,\n isNavigatingAway: false,\n autoScroll: true,\n stream: null,\n messages: [],\n notifications: [],\n prompt: '',\n documents: config.existingDocuments || [],\n isUploading: false,\n isDocumentOperationPending: false,\n documentOperationQueue: null,\n uploadErrors: [],\n isDragOver: false,\n documentBar: null,\n metricsEnabled: !!config.metricsEnabled,\n userLabel: config.userLabel,\n assistantLabel: config.assistantLabel,\n thumbsUpTitle: config.thumbsUpTitle,\n thumbsDownTitle: config.thumbsDownTitle,\n copyTitle: config.copyTitle,\n copiedTitle: config.copiedTitle,\n isRecording: false,\n mediaRecorder: null,\n preRecordingPrompt: '',\n micButton: null,\n speechToTextEnabled: config.chatMode === 'AudioInput' || config.chatMode === 'Conversation',\n textToSpeechEnabled: config.chatMode === 'Conversation' || !!config.textToSpeechEnabled,\n ttsVoiceName: config.ttsVoiceName || null,\n audioChunks: [],\n audioPlayQueue: [],\n isPlayingAudio: false,\n currentAudioElement: null,\n currentAudioUrl: null,\n ttsButton: null,\n ttsPlayingMessageIndex: -1,\n ttsAudioCache: {},\n ttsInstanceId: 'ai-chat-' + Math.random().toString(36).slice(2),\n singleResponseMode: !!config.singleResponseMode,\n conversationModeEnabled: config.chatMode === 'Conversation',\n conversationButton: null,\n isConversationMode: false,\n notificationDismissTimers: {},\n pendingSessionPromise: null,\n pendingSessionResolver: null,\n pendingSessionRejector: null,\n pendingSessionTimeoutId: null,\n copiedMessageIndex: -1,\n copyResetTimeoutId: null,\n activeCopyButton: null,\n };\n },\n computed: {\n lastAssistantIndex() {\n for (var i = this.messages.length - 1; i >= 0; i--) {\n if (this.messages[i].role === 'assistant') {\n return i;\n }\n }\n return -1;\n }\n },\n methods: {\n handleBeforeUnload() {\n this.isNavigatingAway = true;\n },\n handleDragOver(e) {\n if (!config.sessionDocumentsEnabled) return;\n e.preventDefault();\n e.stopPropagation();\n this.isDragOver = true;\n var inputArea = this.inputElement ? this.inputElement.closest('.ai-admin-widget-input, .text-bg-light') : null;\n if (inputArea) inputArea.classList.add('ai-chat-drag-over');\n },\n handleDragLeave(e) {\n if (!config.sessionDocumentsEnabled) return;\n e.preventDefault();\n e.stopPropagation();\n this.isDragOver = false;\n var inputArea = this.inputElement ? this.inputElement.closest('.ai-admin-widget-input, .text-bg-light') : null;\n if (inputArea) inputArea.classList.remove('ai-chat-drag-over');\n },\n handleDrop(e) {\n if (!config.sessionDocumentsEnabled) return;\n e.preventDefault();\n e.stopPropagation();\n this.isDragOver = false;\n var inputArea = this.inputElement ? this.inputElement.closest('.ai-admin-widget-input, .text-bg-light') : null;\n if (inputArea) inputArea.classList.remove('ai-chat-drag-over');\n if (e.dataTransfer && e.dataTransfer.files && e.dataTransfer.files.length > 0) {\n this.uploadFiles(Array.from(e.dataTransfer.files));\n }\n },\n triggerFileInput() {\n if (!config.sessionDocumentsEnabled || this.isDocumentOperationPending) return;\n var fileInput = document.getElementById('ai-chat-doc-input');\n if (fileInput) fileInput.click();\n },\n handleFileInputChange(e) {\n var files = e.target.files ? Array.from(e.target.files) : [];\n if (files && files.length > 0) {\n this.uploadFiles(files);\n }\n e.target.value = '';\n },\n queueDocumentOperation(operation) {\n var self = this;\n var previousOperation = this.documentOperationQueue || Promise.resolve();\n var nextOperation = previousOperation\n .catch(function () { })\n .then(async function () {\n self.isDocumentOperationPending = true;\n try {\n return await operation();\n } finally {\n self.isDocumentOperationPending = false;\n }\n });\n\n this.documentOperationQueue = nextOperation.finally(function () {\n if (self.documentOperationQueue === nextOperation) {\n self.documentOperationQueue = null;\n }\n });\n\n return this.documentOperationQueue;\n },\n async uploadFiles(files) {\n if (!config.uploadDocumentUrl) return;\n\n var filesToUpload = Array.isArray(files) ? files.slice() : Array.from(files || []);\n if (filesToUpload.length === 0) return;\n\n return this.queueDocumentOperation(async () => {\n var sessionId = this.getSessionId();\n var profileId = this.getProfileId();\n\n if (!sessionId) {\n try {\n sessionId = await this.ensureSessionForDocuments(profileId);\n } catch (err) {\n console.error('Failed to create a chat session for document upload:', err);\n this.uploadErrors = [{ fileName: '', error: 'Could not create a chat session for the upload.' }];\n this.renderDocumentBar();\n return;\n }\n }\n\n if (!sessionId) {\n console.warn('Cannot upload documents without a session or profile.');\n this.uploadErrors = [{ fileName: '', error: 'Could not create a chat session for the upload.' }];\n this.renderDocumentBar();\n return;\n }\n\n this.isUploading = true;\n this.uploadErrors = [];\n this.renderDocumentBar();\n try {\n var formData = new FormData();\n formData.append('sessionId', sessionId);\n for (var i = 0; i < filesToUpload.length; i++) {\n formData.append('files', filesToUpload[i]);\n }\n\n var response = await fetch(config.uploadDocumentUrl, {\n method: 'POST',\n body: formData\n });\n\n if (!response.ok) {\n var errorText = await response.text();\n var uploadError = this.extractReadableErrorMessage(errorText, 'Upload failed. Please try again.');\n console.error('Upload failed:', errorText);\n this.uploadErrors = [{ fileName: '', error: uploadError }];\n return;\n }\n\n var result = await response.json();\n\n if (result.sessionId && result.sessionId !== this.getSessionId()) {\n this.initializeSession(result.sessionId);\n }\n\n if (Array.isArray(result.documents)) {\n this.documents = result.documents;\n } else if (result.uploaded && result.uploaded.length > 0) {\n this.documents = this.documents.concat(result.uploaded);\n }\n\n if (result.failed && result.failed.length > 0) {\n this.uploadErrors = result.failed;\n }\n } catch (err) {\n console.error('Upload error:', err);\n this.uploadErrors = [{ fileName: '', error: 'Upload failed. Please try again.' }];\n\n if (this.getSessionId()) {\n this.reloadCurrentSession();\n }\n } finally {\n this.isUploading = false;\n this.renderDocumentBar();\n }\n });\n },\n async removeDocument(doc) {\n if (!config.removeDocumentUrl) return;\n\n return this.queueDocumentOperation(async () => {\n try {\n var sessionId = this.getSessionId();\n var response = await fetch(config.removeDocumentUrl, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ itemId: sessionId, documentId: doc.documentId })\n });\n\n if (response.ok) {\n var result = await response.json();\n\n if (Array.isArray(result.documents)) {\n this.documents = result.documents;\n } else {\n var idx = this.documents.indexOf(doc);\n if (idx > -1) {\n this.documents.splice(idx, 1);\n }\n }\n } else {\n var errorText = await response.text();\n var removeError = this.extractReadableErrorMessage(errorText, 'Failed to remove document. Please try again.');\n console.error('Failed to remove document:', response.status, errorText);\n this.uploadErrors = [{ fileName: doc.fileName || '', error: removeError }];\n if (sessionId) {\n this.reloadCurrentSession();\n }\n this.renderDocumentBar();\n }\n } catch (err) {\n console.error('Remove document error:', err);\n this.uploadErrors = [{ fileName: doc.fileName || '', error: 'Failed to remove document. Please try again.' }];\n if (this.getSessionId()) {\n this.reloadCurrentSession();\n }\n this.renderDocumentBar();\n }\n });\n },\n formatFileSize(bytes) {\n if (bytes < 1024) return bytes + ' B';\n if (bytes < 1024 * 1024) return (bytes / 1024).toFixed(1) + ' KB';\n return (bytes / (1024 * 1024)).toFixed(1) + ' MB';\n },\n renderDocumentBar() {\n if (!this.documentBar) return;\n\n if (!config.sessionDocumentsEnabled) {\n this.documentBar.classList.add('d-none');\n return;\n }\n\n this.documentBar.classList.remove('d-none');\n\n var html = '
';\n html += '
';\n\n for (var i = 0; i < this.documents.length; i++) {\n var doc = this.documents[i];\n var name = doc.fileName || 'Document';\n if (name.length > 20) name = name.substring(0, 17) + '...';\n html += '';\n html += ' ';\n html += this.escapeHtml(name);\n html += ' ';\n html += '';\n }\n\n for (var m = 0; m < this.uploadErrors.length; m++) {\n var failedItem = this.uploadErrors[m];\n var failedName = failedItem.fileName || 'File';\n var errorMsg = failedItem.error || 'Upload failed';\n if (failedName.length > 15) failedName = failedName.substring(0, 12) + '...';\n html += '';\n html += ' ';\n html += this.escapeHtml(failedName);\n html += ' ';\n html += '';\n }\n\n if (this.isUploading) {\n html += '';\n html += ' Uploading...';\n html += '';\n }\n\n html += '';\n html += '
';\n if (config.supportedExtensionsText) {\n html += '
Supported formats: ' + this.escapeHtml(config.supportedExtensionsText) + '
';\n }\n\n html += '
';\n\n this.documentBar.replaceChildren(DOMPurify.sanitize(html, { RETURN_DOM_FRAGMENT: true }));\n\n // Bind remove handlers\n var self = this;\n var closeButtons = this.documentBar.querySelectorAll('[data-doc-index]');\n for (var j = 0; j < closeButtons.length; j++) {\n closeButtons[j].addEventListener('click', (function (idx) {\n return function (e) {\n e.preventDefault();\n e.stopPropagation();\n if (self.isDocumentOperationPending) {\n return;\n }\n\n var docToRemove = self.documents[idx];\n if (docToRemove) self.removeDocument(docToRemove);\n };\n })(parseInt(closeButtons[j].getAttribute('data-doc-index'))));\n }\n\n // Bind error dismiss handlers\n var errorCloseButtons = this.documentBar.querySelectorAll('[data-error-index]');\n for (var n = 0; n < errorCloseButtons.length; n++) {\n errorCloseButtons[n].addEventListener('click', (function (idx) {\n return function (e) {\n e.preventDefault();\n e.stopPropagation();\n self.uploadErrors.splice(idx, 1);\n self.renderDocumentBar();\n };\n })(parseInt(errorCloseButtons[n].getAttribute('data-error-index'))));\n }\n\n // Bind add button\n var addBtn = this.documentBar.querySelector('.ai-chat-doc-add-btn');\n if (addBtn) {\n addBtn.addEventListener('click', function (e) {\n e.preventDefault();\n if (self.isDocumentOperationPending) {\n return;\n }\n self.triggerFileInput();\n });\n }\n },\n escapeHtml(text) {\n var div = document.createElement('div');\n div.textContent = text;\n return div.innerHTML;\n },\n extractReadableErrorMessage(errorText, fallbackMessage) {\n if (!errorText || typeof errorText !== 'string') {\n return fallbackMessage;\n }\n\n var trimmed = errorText.trim();\n if (!trimmed) {\n return fallbackMessage;\n }\n\n if (trimmed.startsWith('{') || trimmed.startsWith('[')) {\n try {\n var parsed = JSON.parse(trimmed);\n var message = parsed?.error || parsed?.message || parsed?.title || parsed?.detail;\n return typeof message === 'string' && message.trim()\n ? message.trim()\n : fallbackMessage;\n } catch (err) {\n return fallbackMessage;\n }\n }\n\n if (/<[^>]+>/.test(trimmed)) {\n return fallbackMessage;\n }\n\n return trimmed;\n },\n normalizeAssistantAppearance(appearance) {\n if (!appearance) {\n return null;\n }\n\n var label = typeof appearance.label === 'string' ? appearance.label.trim() : '';\n var icon = typeof appearance.icon === 'string' ? appearance.icon.trim() : '';\n var cssClass = typeof appearance.cssClass === 'string' ? appearance.cssClass.trim() : '';\n var disableStreamingAnimation = !!appearance.disableStreamingAnimation;\n\n if (!label && !icon && !cssClass && !disableStreamingAnimation) {\n return null;\n }\n\n return {\n label: label,\n icon: icon,\n cssClass: cssClass,\n disableStreamingAnimation: disableStreamingAnimation,\n };\n },\n getAssistantLabel(message) {\n var appearance = message ? this.normalizeAssistantAppearance(message.appearance) : null;\n return appearance && appearance.label ? appearance.label : this.assistantLabel;\n },\n getAssistantRoleClasses(message) {\n var appearance = message ? this.normalizeAssistantAppearance(message.appearance) : null;\n var classes = ['ai-chat-msg-role'];\n\n if (appearance && appearance.cssClass) {\n classes.push(appearance.cssClass);\n } else {\n classes.push('ai-chat-msg-role-assistant');\n }\n\n return classes;\n },\n getAssistantIconClasses(message, index) {\n var appearance = message ? this.normalizeAssistantAppearance(message.appearance) : null;\n return [this.shouldAnimateAssistantIcon(message, index) ? 'ai-streaming-icon' : 'ai-bot-icon', appearance && appearance.cssClass ? appearance.cssClass : ''];\n },\n getAssistantIcon(message) {\n var appearance = message ? this.normalizeAssistantAppearance(message.appearance) : null;\n return appearance && appearance.icon ? appearance.icon : 'fa fa-robot';\n },\n shouldAnimateAssistantIcon(message, index) {\n var appearance = message ? this.normalizeAssistantAppearance(message.appearance) : null;\n return !!message &&\n message.isStreaming &&\n index === this.lastAssistantIndex &&\n !(appearance && appearance.disableStreamingAnimation);\n },\n async startConnection() {\n this.connection = new signalR.HubConnectionBuilder()\n .withUrl(config.signalRHubUrl)\n .withAutomaticReconnect()\n .build();\n\n // Allow long-running operations (e.g., multi-step MCP tool calls)\n // without the client disconnecting prematurely.\n this.connection.serverTimeoutInMilliseconds = 600000;\n this.connection.keepAliveIntervalInMilliseconds = 15000;\n\n this.connection.on(\"LoadSession\", (data) => {\n this.initializeSession(data.sessionId, true);\n this.messages = [];\n this.documents = data.documents || [];\n this.uploadErrors = [];\n\n (data.messages ?? []).forEach(msg => {\n this.addMessage(msg);\n\n this.$nextTick(() => {\n renderChartsInMessage(msg);\n });\n });\n\n // Update feedback icons in the DOM after all messages have rendered.\n this.$nextTick(() => {\n this.refreshAllFeedbackIcons();\n });\n\n // When the session is new (no messages) and an initial prompt is configured,\n // automatically send it as the first user message to trigger an AI response.\n if (this.messages.length === 0 && config.initialPrompt) {\n this.prompt = config.initialPrompt;\n this.sendMessage();\n }\n });\n\n this.connection.on(\"ReceiveError\", (error) => {\n console.error(\"SignalR Error: \", error);\n\n if (this.isRecording) {\n this.stopRecording();\n }\n\n if (widgetBehavior && typeof widgetBehavior.handleReceiveError === 'function') {\n widgetBehavior.handleReceiveError(this, error, config);\n }\n });\n\n this.connection.on(\"MessageRated\", (messageId, userRating) => {\n var msg = this.messages.find(m => m.id === messageId);\n if (msg) {\n msg.userRating = userRating;\n }\n });\n\n this.connection.on(\"ReceiveTranscript\", (sessionId, text, isFinal) => {\n if (this.isConversationMode) {\n if (!isFinal && text) {\n this._conversationPartialTranscript = text;\n var escaped = text.replace(/&/g, '&').replace(//g, '>');\n var html = '

' + escaped + '

';\n\n // Show partial transcript as a live user message.\n if (!this._conversationPartialMessage) {\n this.hidePlaceholder();\n this._conversationPartialMessage = {\n role: 'user',\n content: text,\n htmlContent: html,\n isPartial: true\n };\n this.messages.push(this._conversationPartialMessage);\n } else {\n this._conversationPartialMessage.content = text;\n this._conversationPartialMessage.htmlContent = html;\n }\n this.scrollToBottom();\n }\n return;\n }\n\n if (text && !this._audioInputSent) {\n this.prompt = this.preRecordingPrompt + text;\n if (this.inputElement) {\n this.inputElement.value = this.prompt;\n this.inputElement.dispatchEvent(new Event('input'));\n }\n }\n });\n\n this.connection.on(\"ReceiveConversationUserMessage\", (sessionId, text) => {\n if (text) {\n this.stopAudio();\n\n // If there's an interrupted assistant message still streaming,\n // mark it as done to stop the spinner animation.\n if (this._conversationAssistantMessage) {\n var oldMsg = this.messages[this._conversationAssistantMessage.index];\n if (oldMsg) {\n oldMsg.isStreaming = false;\n }\n this._conversationAssistantMessage = null;\n }\n\n // Replace the partial transcript message with the final one.\n if (this._conversationPartialMessage) {\n var escaped = text.replace(/&/g, '&').replace(//g, '>');\n this._conversationPartialMessage.content = text;\n this._conversationPartialMessage.htmlContent = '

' + escaped + '

';\n this._conversationPartialMessage.isPartial = false;\n this._conversationPartialMessage = null;\n } else {\n this.addMessage({\n role: 'user',\n content: text\n });\n }\n this.scrollToBottom();\n }\n });\n\n this.connection.on(\"ReceiveConversationAssistantToken\", (sessionId, messageId, token, responseId, references, appearance) => {\n if (!this._conversationAssistantMessage) {\n this.stopAudio();\n this.hideTypingIndicator();\n\n // Ensure no stale streaming indicators remain from prior messages.\n for (var j = 0; j < this.messages.length; j++) {\n if (this.messages[j].isStreaming) {\n this.messages[j].isStreaming = false;\n }\n }\n\n var msgIndex = this.messages.length;\n var newMessage = {\n id: messageId,\n role: \"assistant\",\n content: \"\",\n htmlContent: \"\",\n isStreaming: true,\n userRating: null,\n appearance: this.normalizeAssistantAppearance(appearance),\n references: {},\n };\n this.messages.push(newMessage);\n this._conversationAssistantMessage = { index: msgIndex, content: '' };\n }\n\n this._conversationAssistantMessage.content += token;\n var msg = this.messages[this._conversationAssistantMessage.index];\n if (msg) {\n if (!msg.appearance) {\n msg.appearance = this.normalizeAssistantAppearance(appearance);\n }\n msg.rawContent = this._conversationAssistantMessage.content;\n msg.references = normalizeReferences(Object.assign({}, msg.references || {}, references || {}));\n updateMessagePresentation(msg, msg.references);\n this.$nextTick(() => {\n renderChartsInMessage(msg);\n this.scrollToBottom();\n });\n }\n });\n\n this.connection.on(\"ReceiveConversationAssistantComplete\", (sessionId, messageId, references) => {\n if (this._conversationAssistantMessage) {\n var msg = this.messages[this._conversationAssistantMessage.index];\n if (msg) {\n msg.isStreaming = false;\n msg.references = normalizeReferences(Object.assign({}, msg.references || {}, references || {}));\n updateMessagePresentation(msg, msg.references);\n }\n this._conversationAssistantMessage = null;\n }\n });\n\n this.connection.on(\"ReceiveAudioChunk\", (sessionId, base64Audio, contentType) => {\n if (base64Audio) {\n const binaryString = atob(base64Audio);\n const bytes = new Uint8Array(binaryString.length);\n for (let i = 0; i < binaryString.length; i++) {\n bytes[i] = binaryString.charCodeAt(i);\n }\n this.audioChunks.push(bytes);\n }\n });\n\n this.connection.on(\"ReceiveAudioComplete\", (sessionId) => {\n this.playCollectedAudio();\n });\n\n this.connection.on(\"ReceiveNotification\", (notification) => {\n this.receiveNotification(notification);\n });\n\n this.connection.on(\"UpdateNotification\", (notification) => {\n this.updateNotification(notification);\n });\n\n this.connection.on(\"RemoveNotification\", (notificationType) => {\n this.removeNotification(notificationType);\n });\n\n this.connection.onreconnecting(() => {\n console.warn(\"SignalR: reconnecting...\");\n });\n\n this.connection.onreconnected(() => {\n console.info(\"SignalR: reconnected.\");\n\n if (this.isSessionStarted) {\n this.reloadCurrentSession();\n } else if (config.autoCreateSession) {\n this.startNewSession();\n }\n });\n\n this.connection.onclose((error) => {\n if (this.isNavigatingAway) {\n return;\n }\n\n if (error) {\n console.warn(\"SignalR connection closed with error:\", error.message || error);\n }\n });\n\n try {\n await this.connection.start();\n } catch (err) {\n console.error(\"SignalR Connection Error: \", err);\n }\n },\n addMessageInternal(message) {\n if (message.role === 'assistant') {\n message.appearance = this.normalizeAssistantAppearance(message.appearance);\n }\n\n if (message.content && !message.htmlContent) {\n message.htmlContent = parseMarkdownContent(message.content, message);\n }\n this.fireEvent(new CustomEvent(\"addingCoreAIPromotMessage\", { detail: { message: message } }));\n this.messages.push(message);\n\n this.$nextTick(() => {\n this.fireEvent(new CustomEvent(\"addedCoreAIPromotMessage\", { detail: { message: message } }));\n });\n },\n addMessage(message) {\n\n // Ensure userRating is always defined for Vue reactivity.\n if (message.userRating === undefined) {\n message.userRating = null;\n }\n\n if (message.content) {\n message.rawContent = message.rawContent ?? message.content;\n updateMessagePresentation(message, message.references);\n }\n\n this.addMessageInternal(message);\n this.hidePlaceholder();\n\n this.$nextTick(() => {\n // Render any pending charts once the DOM is updated\n renderChartsInMessage(message);\n this.scrollToBottom();\n });\n },\n addMessages(messages) {\n\n for (let i = 0; i < messages.length; i++) {\n this.addMessageInternal(messages[i]);\n }\n\n this.hidePlaceholder();\n this.$nextTick(() => {\n this.scrollToBottom();\n });\n },\n hidePlaceholder() {\n if (this.placeholder) {\n this.placeholder.classList.add('d-none');\n }\n this.isPlaceholderVisible = false;\n },\n showPlaceholder() {\n if (this.placeholder) {\n this.placeholder.classList.remove('d-none');\n }\n this.isPlaceholderVisible = true;\n },\n isOrchestratorAvailable() {\n return config.isOrchestratorAvailable !== false;\n },\n applyOrchestratorAvailability() {\n if (this.isOrchestratorAvailable()) {\n return true;\n }\n\n const unavailableMessage = config.orchestratorUnavailableMessage || \"This orchestrator is not currently available.\";\n\n if (this.inputElement) {\n this.inputElement.disabled = true;\n this.inputElement.value = '';\n this.inputElement.placeholder = unavailableMessage;\n }\n\n if (this.buttonElement) {\n this.buttonElement.disabled = true;\n }\n\n if (this.micButtonElement) {\n this.micButtonElement.disabled = true;\n this.micButtonElement.style.display = 'none';\n }\n\n if (this.conversationButtonElement) {\n this.conversationButtonElement.disabled = true;\n this.conversationButtonElement.style.display = 'none';\n }\n\n return false;\n },\n fireEvent(event) {\n document.dispatchEvent(event);\n },\n isIndicator(message) {\n return message.role === 'indicator';\n },\n sendMessage() {\n if (!this.applyOrchestratorAvailability()) {\n return;\n }\n\n let trimmedPrompt = this.prompt.trim();\n\n if (!trimmedPrompt) {\n return;\n }\n\n // Stop any active recording before sending.\n if (this.isRecording) {\n this.stopRecording();\n }\n\n // Prevent stale ReceiveTranscript events from repopulating the prompt.\n this._audioInputSent = true;\n\n // In single-response mode, clear all previous messages.\n if (this.singleResponseMode) {\n this.messages.splice(0, this.messages.length);\n }\n\n this.addMessage({\n role: 'user',\n content: trimmedPrompt\n });\n\n this.streamMessage(this.getProfileId(), trimmedPrompt, null);\n this.inputElement.value = '';\n this.prompt = '';\n },\n startRecording() {\n if (this.isRecording || !this.connection) {\n return;\n }\n\n navigator.mediaDevices.getUserMedia({ audio: { echoCancellation: true, noiseSuppression: true, autoGainControl: true } })\n .then(stream => {\n var mimeType = MediaRecorder.isTypeSupported('audio/ogg;codecs=opus')\n ? 'audio/ogg;codecs=opus'\n : MediaRecorder.isTypeSupported('audio/webm;codecs=opus')\n ? 'audio/webm;codecs=opus'\n : 'audio/webm';\n\n this.mediaRecorder = new MediaRecorder(stream, {\n mimeType: mimeType,\n audioBitsPerSecond: 128000,\n });\n\n this.preRecordingPrompt = this.prompt;\n this._audioInputSent = false;\n\n var subject = new signalR.Subject();\n var profileId = this.getProfileId();\n var sessionId = this.getSessionId() || '';\n var pendingChunk = Promise.resolve();\n\n this.mediaRecorder.addEventListener('dataavailable', (e) => {\n if (e.data && e.data.size > 0) {\n pendingChunk = pendingChunk.then(async () => {\n var data = await e.data.arrayBuffer();\n var uint8Array = new Uint8Array(data);\n var binaryString = uint8Array.reduce(function (str, byte) { return str + String.fromCharCode(byte); }, '');\n var base64 = btoa(binaryString);\n subject.next(base64);\n });\n }\n });\n\n this.mediaRecorder.addEventListener('stop', () => {\n stream.getTracks().forEach(track => track.stop());\n pendingChunk.then(() => subject.complete());\n });\n\n var language = navigator.language || document.documentElement.lang || 'en-US';\n this.connection.send(\"SendAudioStream\", profileId, sessionId, subject, mimeType, language);\n this.mediaRecorder.start(250);\n this.isRecording = true;\n this.updateMicButton();\n })\n .catch(err => {\n console.error('Microphone access denied:', err);\n });\n },\n stopRecording() {\n if (!this.isRecording || !this.mediaRecorder) {\n return;\n }\n\n this.mediaRecorder.stop();\n this.isRecording = false;\n this.updateMicButton();\n },\n toggleRecording() {\n if (this.isRecording) {\n this.stopRecording();\n } else {\n this.startRecording();\n }\n },\n updateMicButton() {\n if (!this.micButton) {\n return;\n }\n\n if (this.isRecording) {\n this.micButton.classList.add('stt-recording');\n this.micButton.innerHTML = '';\n } else {\n this.micButton.classList.remove('stt-recording');\n this.micButton.innerHTML = '';\n }\n },\n streamMessage(profileId, trimmedPrompt, sessionProfileId) {\n\n if (this.stream) {\n this.stream.dispose();\n this.stream = null;\n }\n\n this.streamingStarted();\n this.showTypingIndicator();\n this.autoScroll = true;\n\n var content = '';\n var references = {};\n var lastResponseId = null;\n\n // Get the index after showing typing indicator.\n var messageIndex = this.messages.length;\n var currentSessionId = this.getSessionId();\n\n this.stream = this.connection.stream(\"SendMessage\", profileId, trimmedPrompt, currentSessionId, sessionProfileId)\n .subscribe({\n next: (chunk) => {\n let message = this.messages[messageIndex];\n\n if (!message) {\n\n if (chunk.sessionId && !currentSessionId) {\n this.initializeSession(chunk.sessionId);\n }\n\n this.hideTypingIndicator();\n // Re-assign the index after hiding the typing indicator.\n messageIndex = this.messages.length;\n let newMessage = {\n id: chunk.messageId,\n role: \"assistant\",\n title: chunk.title,\n content: \"\",\n htmlContent: \"\",\n isStreaming: true,\n userRating: null,\n };\n\n this.messages.push(newMessage);\n\n message = newMessage;\n }\n\n if (chunk.title && (!message.title || message.title !== chunk.title)) {\n message.title = chunk.title;\n }\n\n if (chunk.references && typeof chunk.references === \"object\" && Object.keys(chunk.references).length) {\n\n for (const [key, value] of Object.entries(chunk.references)) {\n references[key] = normalizeReference(value) ?? {};\n }\n }\n\n if (chunk.content) {\n\n // When the responseId changes (e.g., after an internal tool call),\n // insert a line break to visually separate response segments.\n if (chunk.responseId && lastResponseId && chunk.responseId !== lastResponseId) {\n content += '\\n\\n';\n }\n\n if (chunk.responseId) {\n lastResponseId = chunk.responseId;\n }\n\n content += chunk.content;\n }\n\n // Update the existing message\n message.rawContent = content;\n updateMessagePresentation(message, references);\n\n this.messages[messageIndex] = message;\n\n this.$nextTick(() => {\n renderChartsInMessage(message);\n this.scrollToBottom();\n });\n },\n complete: () => {\n this.processReferences(references, messageIndex);\n this.streamingFinished();\n\n let msg = this.messages[messageIndex];\n if (msg) {\n msg.isStreaming = false;\n }\n\n if (!msg || !msg.content) {\n // No content received at all.\n this.hideTypingIndicator();\n }\n\n // Trigger text-to-speech only in conversation mode.\n if (this.isConversationMode && this.textToSpeechEnabled && msg && msg.content) {\n this.synthesizeSpeech(msg.content);\n }\n\n this.stream?.dispose();\n this.stream = null;\n },\n error: (err) => {\n this.processReferences(references, messageIndex);\n this.streamingFinished();\n\n let msg = this.messages[messageIndex];\n if (msg) {\n msg.isStreaming = false;\n }\n\n this.hideTypingIndicator();\n\n if (!this.isNavigatingAway) {\n this.addMessage(this.getServiceDownMessage());\n }\n\n this.stream?.dispose();\n this.stream = null;\n\n console.error(\"Stream error:\", err);\n }\n });\n },\n getServiceDownMessage() {\n let newMessage = {\n role: \"assistant\",\n content: \"Our service is currently unavailable. Please try again later. We apologize for the inconvenience.\",\n htmlContent: \"\",\n };\n\n return newMessage;\n },\n processReferences(references, messageIndex) {\n references = normalizeReferences(references);\n\n if (Object.keys(references).length) {\n\n let message = this.messages[messageIndex];\n message.rawContent = message.rawContent ?? message.content ?? '';\n updateMessagePresentation(message, references);\n\n this.messages[messageIndex] = message;\n\n this.$nextTick(() => {\n renderChartsInMessage(message);\n this.scrollToBottom();\n });\n }\n },\n streamingStarted() {\n var stopIcon = this.buttonElement.getAttribute('data-stop-icon');\n\n if (stopIcon) {\n this.buttonElement.replaceChildren(DOMPurify.sanitize(stopIcon, { RETURN_DOM_FRAGMENT: true }));\n }\n\n if (this.inputElement) {\n this.inputElement.setAttribute('disabled', 'disabled');\n }\n },\n streamingFinished() {\n var startIcon = this.buttonElement.getAttribute('data-start-icon');\n\n if (startIcon) {\n this.buttonElement.replaceChildren(DOMPurify.sanitize(startIcon, { RETURN_DOM_FRAGMENT: true }));\n }\n\n if (this.inputElement) {\n this.inputElement.removeAttribute('disabled');\n this.inputElement.focus();\n }\n\n // Directly manipulate the DOM to stop all streaming animations.\n if (this.chatContainer) {\n var icons = this.chatContainer.querySelectorAll('.ai-streaming-icon');\n for (var i = 0; i < icons.length; i++) {\n icons[i].classList.remove('ai-streaming-icon');\n icons[i].classList.add('ai-bot-icon');\n }\n }\n\n // Also update Vue data for consistency.\n for (var i = 0; i < this.messages.length; i++) {\n if (this.messages[i].isStreaming) {\n this.messages[i].isStreaming = false;\n }\n }\n },\n handleExternalTtsStop(e) {\n if (e?.detail?.sourceId === this.ttsInstanceId) {\n return;\n }\n\n this.stopAudio(false);\n },\n updateTtsPlaybackButtons() {\n if (!this.chatContainer) {\n return;\n }\n\n var buttons = this.chatContainer.querySelectorAll('[data-tts-message-index]');\n\n buttons.forEach(button => {\n var buttonIndex = Number(button.getAttribute('data-tts-message-index'));\n var isPlaying = buttonIndex === this.ttsPlayingMessageIndex;\n\n button.classList.toggle('tts-playing', isPlaying);\n button.setAttribute('title', isPlaying ? 'Pause audio' : 'Read aloud');\n });\n },\n updateCopyButtons() {\n if (!this.chatContainer) {\n return;\n }\n\n var buttons = this.chatContainer.querySelectorAll('[data-copy-message-index]');\n\n buttons.forEach(button => {\n var buttonIndex = Number(button.getAttribute('data-copy-message-index'));\n var isCopied = buttonIndex === this.copiedMessageIndex;\n var iconHtml = isCopied\n ? ''\n : '';\n\n button.classList.toggle('text-success', isCopied);\n button.classList.toggle('text-secondary', !isCopied);\n button.setAttribute('title', isCopied ? this.copiedTitle : this.copyTitle);\n button.replaceChildren(DOMPurify.sanitize(iconHtml, { RETURN_DOM_FRAGMENT: true }));\n });\n },\n setCopyButtonState(button, isCopied) {\n if (!button) {\n return;\n }\n\n var iconHtml = isCopied\n ? ''\n : '';\n\n button.classList.toggle('text-success', isCopied);\n button.classList.toggle('text-secondary', !isCopied);\n button.setAttribute('title', isCopied ? this.copiedTitle : this.copyTitle);\n button.replaceChildren(DOMPurify.sanitize(iconHtml, { RETURN_DOM_FRAGMENT: true }));\n },\n synthesizeSpeech(text, cacheIndex) {\n if (!this.textToSpeechEnabled || !text || !this.connection) {\n return;\n }\n\n this.audioChunks = [];\n this.isPlayingAudio = true;\n this._ttsCacheIndex = cacheIndex !== undefined ? cacheIndex : -1;\n\n this.connection.invoke(\"SynthesizeSpeech\", this.getProfileId(), this.getSessionId(), text, this.ttsVoiceName)\n .catch(err => {\n console.error(\"TTS synthesis error:\", err);\n this.isPlayingAudio = false;\n this.ttsPlayingMessageIndex = -1;\n this._ttsCacheIndex = -1;\n this.$nextTick(() => this.updateTtsPlaybackButtons());\n });\n },\n toggleMessageTts(message, index) {\n if (this.ttsPlayingMessageIndex === index) {\n this.stopAudio();\n return;\n }\n\n this.stopAudio(false);\n window.dispatchEvent(new CustomEvent('crestapps-ai-chat-stop-tts', {\n detail: { sourceId: this.ttsInstanceId }\n }));\n this.ttsPlayingMessageIndex = index;\n this.$nextTick(() => this.updateTtsPlaybackButtons());\n\n if (this.ttsAudioCache[index]) {\n this.playAudioBlob(this.ttsAudioCache[index]);\n return;\n }\n\n this.synthesizeSpeech(message.content, index);\n },\n playCollectedAudio() {\n if (this.audioChunks.length === 0) {\n if (!this.currentAudioElement && this.audioPlayQueue.length === 0) {\n this.isPlayingAudio = false;\n this.ttsPlayingMessageIndex = -1;\n this.$nextTick(() => this.updateTtsPlaybackButtons());\n }\n return;\n }\n\n const totalLength = this.audioChunks.reduce((sum, chunk) => sum + chunk.length, 0);\n const combined = new Uint8Array(totalLength);\n let offset = 0;\n for (const chunk of this.audioChunks) {\n combined.set(chunk, offset);\n offset += chunk.length;\n }\n this.audioChunks = [];\n\n const blob = new Blob([combined], { type: 'audio/mp3' });\n\n if (this._ttsCacheIndex >= 0) {\n this.ttsAudioCache[this._ttsCacheIndex] = blob;\n this._ttsCacheIndex = -1;\n }\n\n // If audio is already playing, queue this blob for sequential playback.\n if (this.currentAudioElement) {\n this.audioPlayQueue.push(blob);\n return;\n }\n\n this.playAudioBlob(blob);\n },\n playAudioBlob(blob) {\n const url = URL.createObjectURL(blob);\n const audio = new Audio(url);\n\n this.currentAudioUrl = url;\n this.currentAudioElement = audio;\n this.isPlayingAudio = true;\n\n audio.addEventListener('ended', () => {\n this.currentAudioElement = null;\n this.currentAudioUrl = null;\n URL.revokeObjectURL(url);\n this.playNextInQueue();\n });\n\n audio.addEventListener('error', () => {\n this.currentAudioElement = null;\n this.currentAudioUrl = null;\n URL.revokeObjectURL(url);\n this.playNextInQueue();\n });\n\n audio.play().catch(err => {\n console.error(\"Audio playback error:\", err);\n this.currentAudioElement = null;\n this.currentAudioUrl = null;\n URL.revokeObjectURL(url);\n this.audioPlayQueue = [];\n this.isPlayingAudio = false;\n this.ttsPlayingMessageIndex = -1;\n this.$nextTick(() => this.updateTtsPlaybackButtons());\n });\n },\n playNextInQueue() {\n if (this.audioPlayQueue.length > 0) {\n var nextBlob = this.audioPlayQueue.shift();\n this.playAudioBlob(nextBlob);\n } else {\n this.isPlayingAudio = false;\n this.ttsPlayingMessageIndex = -1;\n this.$nextTick(() => this.updateTtsPlaybackButtons());\n this.conversationModeOnAudioEnded();\n }\n },\n stopAudio() {\n if (this.currentAudioElement) {\n this.currentAudioElement.pause();\n this.currentAudioElement.currentTime = 0;\n this.currentAudioElement = null;\n }\n if (this.currentAudioUrl) {\n URL.revokeObjectURL(this.currentAudioUrl);\n this.currentAudioUrl = null;\n }\n this.audioChunks = [];\n this.audioPlayQueue = [];\n this.isPlayingAudio = false;\n this.ttsPlayingMessageIndex = -1;\n this.$nextTick(() => this.updateTtsPlaybackButtons());\n },\n toggleConversationMode() {\n if (this.isConversationMode) {\n this.stopConversationMode();\n } else {\n this.startConversationMode();\n }\n },\n startConversationMode() {\n if (!this.conversationModeEnabled || this.isConversationMode || !this.connection) {\n return;\n }\n\n this.isConversationMode = true;\n this.updateConversationButton();\n this._conversationPartialTranscript = '';\n this._conversationAssistantMessage = null;\n this._conversationPartialMessage = null;\n\n // Remove any previous conversation ended notification.\n this.removeNotification('conversation-ended');\n navigator.mediaDevices.getUserMedia({ audio: { echoCancellation: true, noiseSuppression: true, autoGainControl: true } })\n .then(stream => {\n var mimeType = MediaRecorder.isTypeSupported('audio/ogg;codecs=opus')\n ? 'audio/ogg;codecs=opus'\n : MediaRecorder.isTypeSupported('audio/webm;codecs=opus')\n ? 'audio/webm;codecs=opus'\n : 'audio/webm';\n\n this.mediaRecorder = new MediaRecorder(stream, {\n mimeType: mimeType,\n audioBitsPerSecond: 128000,\n });\n\n this._conversationSubject = new signalR.Subject();\n this._conversationStream = stream;\n\n // Create an AnalyserNode for volume-based interrupt detection.\n // During TTS playback, detect when the user speaks above\n // the threshold to stop TTS (interrupt). Audio chunks are\n // always forwarded — browser echo cancellation handles\n // speaker echo so the STT stream has no gaps.\n var AudioCtx = window.AudioContext || window.webkitAudioContext;\n if (AudioCtx) {\n this._conversationAudioCtx = new AudioCtx();\n this._conversationAnalyser = this._conversationAudioCtx.createAnalyser();\n this._conversationAnalyser.fftSize = 256;\n var micSource = this._conversationAudioCtx.createMediaStreamSource(stream);\n micSource.connect(this._conversationAnalyser);\n }\n\n var pendingChunk = Promise.resolve();\n var analyser = this._conversationAnalyser;\n var interruptVolumeThreshold = 30;\n\n this.mediaRecorder.addEventListener('dataavailable', (e) => {\n if (e.data && e.data.size > 0) {\n // During TTS playback, check mic volume to detect\n // user interruption (speaking above threshold).\n if (this.isPlayingAudio && analyser) {\n var freqData = new Uint8Array(analyser.frequencyBinCount);\n analyser.getByteFrequencyData(freqData);\n var sum = 0;\n for (var k = 0; k < freqData.length; k++) { sum += freqData[k]; }\n var avg = sum / freqData.length;\n\n if (avg >= interruptVolumeThreshold) {\n // User is speaking — interrupt TTS playback.\n this.stopAudio();\n }\n }\n\n // Always send audio to STT — browser echo cancellation\n // handles speaker echo; continuous audio avoids gaps\n // that increase recognition latency.\n pendingChunk = pendingChunk.then(async () => {\n var data = await e.data.arrayBuffer();\n var uint8Array = new Uint8Array(data);\n var binaryString = uint8Array.reduce(function (str, byte) { return str + String.fromCharCode(byte); }, '');\n var base64 = btoa(binaryString);\n try {\n this._conversationSubject.next(base64);\n } catch (err) {\n // Subject may have been completed already.\n }\n });\n }\n });\n\n this.mediaRecorder.addEventListener('stop', () => {\n stream.getTracks().forEach(track => track.stop());\n pendingChunk.then(() => {\n try {\n this._conversationSubject.complete();\n } catch (err) {\n // Already completed.\n }\n });\n });\n\n var profileId = this.getProfileId();\n var sessionId = this.getSessionId() || '';\n var language = navigator.language || document.documentElement.lang || 'en-US';\n\n this.connection.send(\"StartConversation\", profileId, sessionId, this._conversationSubject, mimeType, language);\n this.mediaRecorder.start(250);\n this.isRecording = true;\n })\n .catch(err => {\n console.error('Microphone access denied:', err);\n this.isConversationMode = false;\n this.updateConversationButton();\n });\n },\n stopConversationMode() {\n if (!this.isConversationMode) {\n return;\n }\n\n this.isConversationMode = false;\n this.updateConversationButton();\n\n // Signal the server to cancel all in-progress STT/TTS streams immediately.\n if (this.connection) {\n this.connection.invoke(\"StopConversation\").catch(function () { });\n }\n\n if (this.isRecording && this.mediaRecorder) {\n this.mediaRecorder.stop();\n this.isRecording = false;\n }\n\n this.stopAudio();\n this._conversationPartialTranscript = '';\n this._conversationPartialMessage = null;\n\n // Clean up the AudioContext used for volume monitoring.\n if (this._conversationAudioCtx) {\n this._conversationAudioCtx.close().catch(function () { });\n this._conversationAudioCtx = null;\n this._conversationAnalyser = null;\n }\n\n // Mark any in-flight assistant message as done to stop the spinner.\n if (this._conversationAssistantMessage) {\n var msg = this.messages[this._conversationAssistantMessage.index];\n if (msg) {\n msg.isStreaming = false;\n }\n this._conversationAssistantMessage = null;\n }\n\n // Safety net: clear all lingering streaming indicators.\n for (var i = 0; i < this.messages.length; i++) {\n if (this.messages[i].isStreaming) {\n this.messages[i].isStreaming = false;\n }\n }\n\n // Show a \"conversation ended\" notification system message.\n this.receiveNotification({\n type: 'conversation-ended',\n content: 'Conversation ended.',\n icon: 'fa-solid fa-circle-check',\n dismissible: true,\n autoDismissMs: 5000\n });\n },\n updateConversationButton() {\n if (!this.conversationButton) {\n return;\n }\n\n if (this.isConversationMode) {\n this.conversationButton.classList.add('active', 'btn-primary');\n this.conversationButton.classList.remove('btn-dark', 'btn-outline-dark', 'btn-outline-secondary');\n this.conversationButton.title = this.conversationButton.getAttribute('data-end-title') || 'End Conversation';\n var endHtml = this.conversationButton.getAttribute('data-end-html');\n if (endHtml) {\n this.conversationButton.replaceChildren(DOMPurify.sanitize(endHtml, { RETURN_DOM_FRAGMENT: true }));\n }\n } else {\n this.conversationButton.classList.remove('active', 'btn-primary');\n this.conversationButton.classList.remove('btn-dark', 'btn-outline-secondary');\n this.conversationButton.classList.add('btn-outline-dark');\n this.conversationButton.blur();\n this.conversationButton.title = this.conversationButton.getAttribute('data-start-title') || 'Start Conversation';\n var startHtml = this.conversationButton.getAttribute('data-start-html');\n if (startHtml) {\n this.conversationButton.replaceChildren(DOMPurify.sanitize(startHtml, { RETURN_DOM_FRAGMENT: true }));\n }\n }\n },\n conversationModeSendPrompt() {\n // Legacy: only used by AudioInput mode's ReceiveTranscript.\n },\n conversationModeOnAudioEnded() {\n // Legacy: in conversation mode, audio playback continuation\n // is handled by the persistent stream. This method is only\n // called from playCollectedAudio for non-conversation TTS.\n },\n generatePrompt(element) {\n if (!element) {\n console.error('The element paramter is required.');\n\n return;\n }\n\n let templateProfileId = element.getAttribute('data-profile-id');\n let sessionId = this.getSessionId();\n let sessionProfileId = this.getProfileId();\n\n if (!templateProfileId || !sessionId) {\n\n console.error('The given element is missing data-profile-id or the session has not yet started.');\n return;\n }\n\n // streamMessage() already shows the typing indicator.\n this.streamMessage(templateProfileId, null, sessionProfileId);\n },\n createSessionUrl(baseUrl, param, value) {\n\n const fullUrl = baseUrl.toLowerCase().startsWith('http') ? baseUrl : window.location.origin + baseUrl;\n const url = new URL(fullUrl);\n\n url.searchParams.set(param, value);\n\n return url.toString();\n },\n showTypingIndicator() {\n this.addMessage({\n role: 'indicator',\n htmlContent: config.indicatorTemplate\n });\n },\n hideTypingIndicator() {\n const originalLength = this.messages.length;\n this.messages = this.messages.filter(msg => msg.role !== 'indicator');\n const removedCount = originalLength - this.messages.length;\n return removedCount;\n },\n receiveNotification(notification) {\n if (!notification || !notification.type) {\n return;\n }\n this.clearNotificationDismiss(notification.type);\n var existingIndex = this.notifications.findIndex(n => n.type === notification.type);\n if (existingIndex >= 0) {\n this.notifications.splice(existingIndex, 1, notification);\n } else {\n this.notifications.push(notification);\n }\n this.scheduleNotificationDismiss(notification);\n this.$nextTick(() => {\n this.scrollToBottom();\n });\n },\n updateNotification(notification) {\n if (!notification || !notification.type) {\n return;\n }\n this.clearNotificationDismiss(notification.type);\n var existingIndex = this.notifications.findIndex(n => n.type === notification.type);\n if (existingIndex >= 0) {\n this.notifications.splice(existingIndex, 1, notification);\n this.scheduleNotificationDismiss(notification);\n }\n },\n scheduleNotificationDismiss(notification) {\n if (!notification || !notification.type || !notification.autoDismissMs || notification.autoDismissMs <= 0) {\n return;\n }\n this.notificationDismissTimers[notification.type] = setTimeout(() => {\n this.removeNotification(notification.type);\n }, notification.autoDismissMs);\n },\n clearNotificationDismiss(notificationType) {\n var timerId = this.notificationDismissTimers[notificationType];\n if (!timerId) {\n return;\n }\n clearTimeout(timerId);\n delete this.notificationDismissTimers[notificationType];\n },\n removeNotification(notificationType) {\n this.clearNotificationDismiss(notificationType);\n this.notifications = this.notifications.filter(n => n.type !== notificationType);\n },\n dismissNotification(notificationType) {\n this.removeNotification(notificationType);\n },\n handleNotificationAction(notificationType, actionName) {\n if (!this.connection) {\n return;\n }\n var sessionId = this.getSessionId();\n this.connection.invoke(\"HandleNotificationAction\", sessionId, notificationType, actionName).catch(function (err) {\n console.error(\"Error handling notification action:\", err);\n });\n },\n scrollToBottom() {\n if (!this.autoScroll) {\n return;\n }\n setTimeout(() => {\n this.chatContainer.scrollTop = this.chatContainer.scrollHeight - this.chatContainer.clientHeight;\n }, 50);\n },\n handleUserInput(event) {\n this.prompt = event.target.value;\n },\n getProfileId() {\n return this.inputElement\n ? this.inputElement.getAttribute('data-profile-id')\n : null;\n },\n setSessionId(sessionId) {\n if (!this.inputElement) {\n return;\n }\n\n this.inputElement.setAttribute('data-session-id', sessionId || '');\n },\n resetSession() {\n this.stopRecording();\n this.rejectPendingSessionRequest('Session was reset.');\n this.setSessionId('');\n this.isSessionStarted = false;\n this.sessionRating = null;\n this.messages = [];\n this.documents = [];\n if (!config.autoCreateSession) {\n this.showPlaceholder();\n }\n\n if (config.autoCreateSession) {\n this.startNewSession();\n }\n\n if (widgetBehavior && typeof widgetBehavior.onSessionReset === 'function') {\n widgetBehavior.onSessionReset(this, config);\n }\n },\n startNewSession() {\n if (!this.applyOrchestratorAvailability()) {\n return;\n }\n\n const profileId = this.getProfileId();\n if (!profileId || !this.connection) {\n return;\n }\n\n this.requestNewSession(profileId).catch(err => console.error(err));\n },\n async ensureSessionForDocuments(profileId) {\n var sessionId = this.getSessionId();\n if (sessionId) {\n return sessionId;\n }\n\n if (!profileId || !this.connection) {\n return null;\n }\n\n return await this.requestNewSession(profileId);\n },\n requestNewSession(profileId) {\n if (this.pendingSessionPromise) {\n return this.pendingSessionPromise;\n }\n\n if (!profileId || !this.connection) {\n return Promise.resolve(null);\n }\n\n this.pendingSessionPromise = new Promise((resolve, reject) => {\n this.pendingSessionResolver = resolve;\n this.pendingSessionRejector = reject;\n this.pendingSessionTimeoutId = window.setTimeout(() => {\n this.rejectPendingSessionRequest('Timed out while creating a chat session.');\n }, 15000);\n });\n\n this.connection.invoke(\"StartSession\", profileId, null).catch(err => {\n this.rejectPendingSessionRequest(err);\n });\n\n return this.pendingSessionPromise;\n },\n resolvePendingSessionRequest(sessionId) {\n if (this.pendingSessionResolver) {\n this.pendingSessionResolver(sessionId);\n }\n\n this.clearPendingSessionRequest();\n },\n rejectPendingSessionRequest(error) {\n if (this.pendingSessionRejector) {\n this.pendingSessionRejector(error);\n }\n\n this.clearPendingSessionRequest();\n },\n clearPendingSessionRequest() {\n if (this.pendingSessionTimeoutId) {\n window.clearTimeout(this.pendingSessionTimeoutId);\n }\n\n this.pendingSessionPromise = null;\n this.pendingSessionResolver = null;\n this.pendingSessionRejector = null;\n this.pendingSessionTimeoutId = null;\n },\n initializeApp() {\n this.inputElement = document.querySelector(config.inputElementSelector);\n this.buttonElement = document.querySelector(config.sendButtonElementSelector);\n this.chatContainer = document.querySelector(config.chatContainerElementSelector);\n this.placeholder = document.querySelector(config.placeholderElementSelector);\n\n if (!this.inputElement || !this.buttonElement || !this.chatContainer || !this.placeholder) {\n console.error('AI chat app could not initialize because one or more required elements were not found.', {\n inputElementSelector: config.inputElementSelector,\n sendButtonElementSelector: config.sendButtonElementSelector,\n chatContainerElementSelector: config.chatContainerElementSelector,\n placeholderElementSelector: config.placeholderElementSelector\n });\n\n return false;\n }\n\n this.applyOrchestratorAvailability();\n\n const sessionId = this.getSessionId();\n if (!hasWidgetConfig && sessionId) {\n this.loadSession(sessionId);\n } else if (this.isOrchestratorAvailable() && config.autoCreateSession && !hasWidgetConfig && !sessionId) {\n this.startNewSession();\n }\n\n // Initialize document bar if enabled.\n if (config.sessionDocumentsEnabled && config.documentBarSelector) {\n this.documentBar = document.querySelector(config.documentBarSelector);\n if (this.documentBar) {\n this.renderDocumentBar();\n\n // Create hidden file input for document uploads.\n var fileInput = document.createElement('input');\n fileInput.type = 'file';\n fileInput.id = 'ai-chat-doc-input';\n fileInput.className = 'd-none';\n fileInput.multiple = true;\n if (config.allowedExtensions) {\n fileInput.accept = config.allowedExtensions;\n }\n fileInput.addEventListener('change', (e) => this.handleFileInputChange(e));\n this.documentBar.parentElement.appendChild(fileInput);\n\n // Set up drag-and-drop on the input area.\n var inputArea = this.inputElement ? this.inputElement.closest('.ai-admin-widget-input, .text-bg-light') : null;\n if (inputArea) {\n inputArea.addEventListener('dragover', (e) => this.handleDragOver(e));\n inputArea.addEventListener('dragleave', (e) => this.handleDragLeave(e));\n inputArea.addEventListener('drop', (e) => this.handleDrop(e));\n }\n }\n }\n\n // Pause auto-scroll when the user manually scrolls up during streaming.\n this.chatContainer.addEventListener('scroll', () => {\n if (!this.stream) {\n return;\n }\n const threshold = 30;\n const atBottom = this.chatContainer.scrollHeight - this.chatContainer.clientHeight - this.chatContainer.scrollTop <= threshold;\n this.autoScroll = atBottom;\n });\n\n this.inputElement.addEventListener('keydown', event => {\n\n if (this.stream != null) {\n return;\n }\n\n if (event.key === \"Enter\" && !event.shiftKey) {\n event.preventDefault();\n this.buttonElement.click();\n }\n });\n\n this.inputElement.addEventListener('input', (e) => {\n this.handleUserInput(e);\n\n if (e.target.value.trim()) {\n this.buttonElement.removeAttribute('disabled');\n } else {\n this.buttonElement.setAttribute('disabled', true);\n }\n });\n\n this.buttonElement.addEventListener('click', () => {\n\n if (this.stream != null) {\n this.stream.dispose();\n this.stream = null;\n\n this.streamingFinished();\n this.hideTypingIndicator();\n\n // Clean up: remove empty assistant message or stop streaming animation.\n if (this.messages.length > 0) {\n const lastMsg = this.messages[this.messages.length - 1];\n if (lastMsg.role === 'assistant' && !lastMsg.content) {\n this.messages.pop();\n } else if (lastMsg.isStreaming) {\n lastMsg.isStreaming = false;\n }\n }\n\n return;\n }\n\n this.sendMessage();\n });\n\n const promptGenerators = document.getElementsByClassName('profile-generated-prompt');\n\n for (var i = 0; i < promptGenerators.length; i++) {\n promptGenerators[i].addEventListener('click', (e) => {\n e.preventDefault();\n this.generatePrompt(e.target);\n });\n }\n\n const chatSessions = document.getElementsByClassName('chat-session-history-item');\n\n for (var i = 0; i < chatSessions.length; i++) {\n chatSessions[i].addEventListener('click', (e) => {\n e.preventDefault();\n\n var sessionId = e.target.getAttribute('data-session-id');\n\n if (!sessionId) {\n console.error('an element with the class chat-session-history-item with no data-session-id set.');\n\n return;\n }\n\n this.loadSession(sessionId);\n this.showChatScreen();\n });\n }\n\n const initialMessages = Array.isArray(config.messages) ? config.messages : [];\n\n for (let i = 0; i < initialMessages.length; i++) {\n this.addMessage(initialMessages[i]);\n }\n\n // Update feedback icons in the DOM after initial messages have rendered.\n this.$nextTick(() => {\n this.refreshAllFeedbackIcons();\n });\n\n // Delegate click for code block copy buttons.\n if (this.chatContainer) {\n this.chatContainer.addEventListener('click', (e) => {\n var btn = e.target.closest('.ai-code-copy-btn');\n if (!btn) {\n return;\n }\n\n var block = btn.closest('.ai-code-block') || btn.closest('pre');\n if (!block) {\n return;\n }\n\n var codeEl = block.querySelector('code');\n if (codeEl) {\n navigator.clipboard.writeText(codeEl.textContent);\n var copiedText = config.codeCopiedText || 'Copied!';\n btn.innerHTML = ' ' + copiedText;\n setTimeout(() => {\n btn.innerHTML = '';\n }, 2000);\n }\n });\n }\n\n // Initialize speech-to-text microphone button.\n if (this.speechToTextEnabled && config.micButtonElementSelector) {\n this.micButton = document.querySelector(config.micButtonElementSelector);\n if (this.micButton) {\n this.micButton.style.display = '';\n this.micButton.addEventListener('click', () => {\n this.toggleRecording();\n });\n }\n }\n\n // Initialize conversation mode button.\n if (this.conversationModeEnabled && config.conversationButtonElementSelector) {\n this.conversationButton = document.querySelector(config.conversationButtonElementSelector);\n if (this.conversationButton) {\n this.conversationButton.addEventListener('click', () => {\n this.toggleConversationMode();\n });\n }\n }\n\n return true;\n },\n loadSession(sessionId) {\n this.connection.invoke(\"LoadSession\", sessionId).catch(err => console.error(err));\n },\n reloadCurrentSession() {\n\n var sessionId = this.getSessionId();\n if (sessionId) {\n this.loadSession(sessionId);\n }\n },\n initializeSession(sessionId, force) {\n if (this.isSessionStarted && !force) {\n if (sessionId && this.getSessionId() === sessionId) {\n this.resolvePendingSessionRequest(sessionId);\n }\n\n return\n }\n this.fireEvent(new CustomEvent(\"initializingSessionCoreAIChat\", { detail: { sessionId: sessionId } }))\n this.setSessionId(sessionId);\n this.isSessionStarted = true;\n this.resolvePendingSessionRequest(sessionId);\n\n if (widgetBehavior && typeof widgetBehavior.onSessionInitialized === 'function') {\n widgetBehavior.onSessionInitialized(this, sessionId, config);\n }\n },\n getSessionId() {\n let sessionId = this.inputElement\n ? this.inputElement.getAttribute('data-session-id')\n : null;\n\n if (!sessionId && widgetBehavior && typeof widgetBehavior.resolveSessionId === 'function') {\n sessionId = widgetBehavior.resolveSessionId(this, config);\n }\n\n return sessionId;\n },\n clearCopiedMessageState() {\n if (this.copyResetTimeoutId) {\n window.clearTimeout(this.copyResetTimeoutId);\n this.copyResetTimeoutId = null;\n }\n\n if (this.activeCopyButton) {\n this.setCopyButtonState(this.activeCopyButton, false);\n this.activeCopyButton = null;\n }\n\n this.copiedMessageIndex = -1;\n },\n copyResponse(message, index, event) {\n const text = message && typeof message === 'object'\n ? message.copyContent ?? message.content ?? ''\n : message ?? '';\n const button = event?.currentTarget || event?.target?.closest?.('[data-copy-message-index]') || null;\n\n navigator.clipboard.writeText(text)\n .then(() => {\n this.clearCopiedMessageState();\n this.copiedMessageIndex = typeof index === 'number' ? index : -1;\n this.activeCopyButton = button;\n\n if (button) {\n this.setCopyButtonState(button, true);\n } else {\n this.$nextTick(() => this.updateCopyButtons());\n }\n\n this.copyResetTimeoutId = window.setTimeout(() => {\n this.clearCopiedMessageState();\n this.$nextTick(() => this.updateCopyButtons());\n }, Number(config.copyResetDelayMs) || 2000);\n })\n .catch(err => console.error('Failed to copy response:', err));\n },\n updateFeedbackIcons(container, userRating) {\n if (!container) {\n return;\n }\n\n var upBtn = container.querySelector('.rate-up-btn');\n var downBtn = container.querySelector('.rate-down-btn');\n\n // Keep feedback icons as simple span-based Font Awesome markup so\n // later state updates do not depend on i2svg replacement.\n if (upBtn) {\n var upClass = userRating === true ? 'fa-solid fa-thumbs-up' : 'fa-regular fa-thumbs-up';\n var upIcon = document.createElement('span');\n upIcon.className = upClass;\n upIcon.style.fontSize = '0.9rem';\n upBtn.textContent = '';\n upBtn.appendChild(upIcon);\n }\n\n if (downBtn) {\n var downClass = userRating === false ? 'fa-solid fa-thumbs-down' : 'fa-regular fa-thumbs-down';\n var downIcon = document.createElement('span');\n downIcon.className = downClass;\n downIcon.style.fontSize = '0.9rem';\n downBtn.textContent = '';\n downBtn.appendChild(downIcon);\n }\n },\n refreshAllFeedbackIcons() {\n var containers = this.$el.querySelectorAll('.ai-chat-message-assistant-feedback');\n\n for (var i = 0; i < containers.length; i++) {\n var msgId = containers[i].getAttribute('data-message-id');\n var msg = this.messages.find(m => m.id === msgId);\n\n if (msg) {\n this.updateFeedbackIcons(containers[i], msg.userRating);\n }\n }\n },\n rateMessage(message, isPositive, event) {\n var sessionId = this.getSessionId();\n\n if (!sessionId || !message.id || !this.connection) {\n return;\n }\n\n // Toggle: clicking the same rating again clears it.\n var newRating = message.userRating === isPositive ? null : isPositive;\n message.userRating = newRating;\n\n // Find the feedback container by message ID for reliable DOM targeting.\n var feedbackContainer = this.$el.querySelector(\n '.ai-chat-message-assistant-feedback[data-message-id=\"' + message.id + '\"]'\n );\n\n this.updateFeedbackIcons(feedbackContainer, newRating);\n\n // Trigger spark animation after Font Awesome has re-processed icons.\n if (newRating !== null && feedbackContainer) {\n setTimeout(() => {\n var btnClass = isPositive ? '.rate-up-btn' : '.rate-down-btn';\n var btn = feedbackContainer.querySelector(btnClass);\n\n if (btn) {\n btn.classList.remove('spark-effect');\n void btn.offsetWidth;\n btn.classList.add('spark-effect');\n btn.addEventListener('animationend', function onEnd() {\n btn.removeEventListener('animationend', onEnd);\n btn.classList.remove('spark-effect');\n });\n }\n }, 50);\n }\n\n this.connection.invoke(\"RateMessage\", sessionId, message.id, isPositive).catch(function (err) {\n console.error('Failed to rate message:', err);\n });\n }\n },\n watch: {\n documents: {\n handler() {\n this.renderDocumentBar();\n if (widgetBehavior && typeof widgetBehavior.onDocumentsChanged === 'function') {\n widgetBehavior.onDocumentsChanged(this, this.documents, config);\n }\n },\n deep: true\n },\n isUploading() { this.renderDocumentBar(); },\n isDocumentOperationPending() { this.renderDocumentBar(); },\n isPlayingAudio() {\n // Reserved for future use — volume-based interrupt detection\n // no longer mutes tracks; browser echo cancellation handles echo.\n },\n copiedMessageIndex() {\n this.$nextTick(() => this.updateCopyButtons());\n },\n isConversationMode(active) {\n // Hide/show mic button.\n if (this.micButton) {\n this.micButton.style.display = active ? 'none' : (this.speechToTextEnabled ? '' : 'none');\n }\n\n // Hide/show send button.\n if (this.buttonElement) {\n this.buttonElement.style.display = active ? 'none' : '';\n }\n\n // Disable/enable textarea.\n if (this.inputElement) {\n this.inputElement.disabled = active;\n if (active) {\n this.inputElement.placeholder = '';\n }\n }\n }\n },\n mounted() {\n (async () => {\n await this.startConnection();\n const isInitialized = this.initializeApp();\n if (isInitialized && hasWidgetConfig && widgetBehavior && typeof widgetBehavior.onMounted === 'function') {\n widgetBehavior.onMounted(this, config);\n }\n\n this.$nextTick(() => {\n this.updateCopyButtons();\n refreshFontAwesomeIcons(this.$el);\n this.fontAwesomeObserver = observeFontAwesomeIcons(this.$el);\n });\n })();\n\n window.addEventListener('beforeunload', this.handleBeforeUnload);\n window.addEventListener('crestapps-ai-chat-stop-tts', this.handleExternalTtsStop);\n },\n beforeUnmount() {\n window.removeEventListener('beforeunload', this.handleBeforeUnload);\n window.removeEventListener('crestapps-ai-chat-stop-tts', this.handleExternalTtsStop);\n\n if (this.fontAwesomeObserver) {\n this.fontAwesomeObserver.disconnect();\n this.fontAwesomeObserver = null;\n }\n\n this.clearCopiedMessageState();\n this.stopAudio(false);\n\n if (this.stream) {\n this.stream.dispose();\n this.stream = null;\n }\n if (this.connection) {\n this.connection.stop();\n }\n\n if (widgetBehavior && typeof widgetBehavior.onBeforeUnmount === 'function') {\n widgetBehavior.onBeforeUnmount(this, config);\n }\n },\n template: config.messageTemplate\n };\n\n const app = Vue.createApp(appDefinition).mount(config.appElementSelector);\n\n if (widgetBehavior && typeof widgetBehavior.attach === 'function') {\n widgetBehavior.attach(app, config);\n }\n\n return app;\n };\n\n const autoInitializeSelector = '[data-coreai-chat-config],[data-coreai-chat-app-element-selector]';\n\n function getAttributeValue(element, attributeName) {\n const value = element.getAttribute(attributeName);\n return value === null || value === '' ? null : value;\n }\n\n function parseBooleanAttributeValue(value) {\n if (value === null || value === undefined) {\n return null;\n }\n\n if (typeof value === 'boolean') {\n return value;\n }\n\n const normalized = String(value).trim().toLowerCase();\n if (normalized === 'true') {\n return true;\n }\n\n if (normalized === 'false') {\n return false;\n }\n\n return null;\n }\n\n function parseJsonAttribute(element, attributeName, description) {\n const rawValue = getAttributeValue(element, attributeName);\n if (!rawValue) {\n return null;\n }\n\n try {\n return JSON.parse(rawValue);\n } catch (error) {\n console.error('Failed to parse ' + description + ' JSON.', error);\n return null;\n }\n }\n\n function buildConfigFromDataAttributes(element, options) {\n const settings = options || {};\n\n if (element.hasAttribute('data-coreai-chat-widget-container-selector') && settings.allowWidgetHost !== true) {\n return null;\n }\n\n const appElementSelector = getAttributeValue(element, 'data-coreai-chat-app-element-selector');\n if (!appElementSelector) {\n return null;\n }\n\n const config = {\n signalRHubUrl: getAttributeValue(element, 'data-coreai-chat-signalr-hub-url'),\n appElementSelector: appElementSelector,\n chatContainerElementSelector: getAttributeValue(element, 'data-coreai-chat-container-element-selector'),\n inputElementSelector: getAttributeValue(element, 'data-coreai-chat-input-element-selector'),\n sendButtonElementSelector: getAttributeValue(element, 'data-coreai-chat-send-button-element-selector'),\n placeholderElementSelector: getAttributeValue(element, 'data-coreai-chat-placeholder-element-selector'),\n messages: parseJsonAttribute(element, 'data-coreai-chat-messages', 'CoreAI chat messages') ?? undefined,\n chatMode: getAttributeValue(element, 'data-coreai-chat-mode'),\n micButtonElementSelector: getAttributeValue(element, 'data-coreai-chat-mic-button-element-selector'),\n conversationButtonElementSelector: getAttributeValue(element, 'data-coreai-chat-conversation-button-element-selector'),\n ttsVoiceName: getAttributeValue(element, 'data-coreai-chat-tts-voice-name'),\n documentBarSelector: getAttributeValue(element, 'data-coreai-chat-document-bar-selector'),\n uploadDocumentUrl: getAttributeValue(element, 'data-coreai-chat-upload-document-url'),\n removeDocumentUrl: getAttributeValue(element, 'data-coreai-chat-remove-document-url'),\n allowedExtensions: getAttributeValue(element, 'data-coreai-chat-allowed-extensions'),\n supportedExtensionsText: getAttributeValue(element, 'data-coreai-chat-supported-extensions-text'),\n existingDocuments: parseJsonAttribute(element, 'data-coreai-chat-existing-documents', 'CoreAI chat existing documents') ?? undefined,\n initialPrompt: getAttributeValue(element, 'data-coreai-chat-initial-prompt'),\n userLabel: getAttributeValue(element, 'data-coreai-chat-user-label'),\n assistantLabel: getAttributeValue(element, 'data-coreai-chat-assistant-label'),\n copyTitle: getAttributeValue(element, 'data-coreai-chat-copy-title'),\n copiedTitle: getAttributeValue(element, 'data-coreai-chat-copied-title'),\n };\n\n const booleanAttributes = {\n metricsEnabled: 'data-coreai-chat-metrics-enabled',\n textToSpeechEnabled: 'data-coreai-chat-text-to-speech-enabled',\n sessionDocumentsEnabled: 'data-coreai-chat-session-documents-enabled',\n autoCreateSession: 'data-coreai-chat-auto-create-session',\n singleResponseMode: 'data-coreai-chat-single-response-mode',\n };\n\n Object.keys(booleanAttributes).forEach(key => {\n const parsed = parseBooleanAttributeValue(getAttributeValue(element, booleanAttributes[key]));\n if (parsed !== null) {\n config[key] = parsed;\n }\n });\n\n return compactObject(config);\n }\n\n function buildConfigFromElement(element, options) {\n const jsonConfig = parseJsonAttribute(element, 'data-coreai-chat-config', 'CoreAI chat config');\n const attributeConfig = buildConfigFromDataAttributes(element, options);\n\n if (!jsonConfig && !attributeConfig) {\n return null;\n }\n\n return Object.assign({}, jsonConfig || {}, attributeConfig || {});\n }\n\n function initializeFromElement(element) {\n if (!element || element.dataset.coreAiChatInitialized === 'true') {\n return element ? element.__coreAIChatApp || null : null;\n }\n\n const config = buildConfigFromElement(element);\n if (!config) {\n return null;\n }\n\n const app = initialize(config);\n if (!app) {\n return null;\n }\n\n element.dataset.coreAiChatInitialized = 'true';\n element.__coreAIChatApp = app;\n\n return app;\n }\n\n function scanForAutoInitialization(root) {\n if (!root || typeof root.querySelectorAll !== 'function') {\n return;\n }\n\n if (typeof root.matches === 'function' && root.matches(autoInitializeSelector)) {\n initializeFromElement(root);\n }\n\n root.querySelectorAll(autoInitializeSelector).forEach(initializeFromElement);\n }\n\n function startAutoInitialization() {\n scanForAutoInitialization(document);\n\n if (typeof MutationObserver === 'undefined') {\n return;\n }\n\n const observer = new MutationObserver(mutations => {\n mutations.forEach(mutation => {\n mutation.addedNodes.forEach(node => {\n if (node && node.nodeType === 1) {\n scanForAutoInitialization(node);\n }\n });\n });\n });\n\n observer.observe(document.body, {\n childList: true,\n subtree: true,\n });\n }\n\n if (document.readyState === 'loading') {\n document.addEventListener('DOMContentLoaded', startAutoInitialization, { once: true });\n } else {\n startAutoInitialization();\n }\n\n return {\n initialize: initialize,\n initializeFromElement: initializeFromElement,\n buildConfigFromElement: buildConfigFromElement,\n };\n}();\n\n// Download chart as image via event delegation (DOMPurify strips inline onclick).\ndocument.addEventListener('click', function (e) {\n const btn = e.target.closest('.download-chart-btn');\n if (!btn) {\n return;\n }\n const chartId = btn.getAttribute('data-chart-id');\n const canvas = chartId ? document.getElementById(chartId) : null;\n if (!canvas) {\n console.error('Chart canvas not found:', chartId);\n return;\n }\n const link = document.createElement('a');\n link.download = 'chart-' + chartId + '.png';\n link.href = canvas.toDataURL('image/png');\n link.click();\n});\n\n// Intercept download clicks for data-URI images and convert to blob downloads.\ndocument.addEventListener('click', function (e) {\n const link = e.target.closest('.ai-download-image');\n if (!link) {\n return;\n }\n\n const container = link.closest('.generated-image-container');\n const img = container?.querySelector('img');\n if (!img) {\n return;\n }\n\n const src = img.src;\n if (!src || !src.startsWith('data:')) {\n return; // Normal URL – let the default behaviour handle it.\n }\n\n e.preventDefault();\n\n fetch(src)\n .then(function (res) { return res.blob(); })\n .then(function (blob) {\n const url = URL.createObjectURL(blob);\n const a = document.createElement('a');\n a.href = url;\n a.download = link.getAttribute('download') || 'generated-image.png';\n document.body.appendChild(a);\n a.click();\n document.body.removeChild(a);\n setTimeout(function () { URL.revokeObjectURL(url); }, 100);\n })\n .catch(function (err) { console.error('Failed to download image:', err); });\n});\n"]} +{"version":3,"sources":["ai-chat.js"],"names":["e","t","r","Symbol","n","iterator","o","toStringTag","i","c","prototype","Generator","u","Object","create","_regeneratorDefine2","f","p","y","G","v","a","d","bind","length","l","TypeError","call","done","value","GeneratorFunction","GeneratorFunctionPrototype","getPrototypeOf","setPrototypeOf","__proto__","displayName","_regenerator","w","m","defineProperty","_regeneratorDefine","_invoke","enumerable","configurable","writable","asyncGeneratorStep","Promise","resolve","then","_asyncToGenerator","arguments","apply","_next","_throw","_toConsumableArray","_arrayWithoutHoles","_iterableToArray","_unsupportedIterableToArray","_nonIterableSpread","Array","from","isArray","_arrayLikeToArray","_objectWithoutProperties","_objectWithoutPropertiesLoose","getOwnPropertySymbols","indexOf","propertyIsEnumerable","hasOwnProperty","_createForOfIteratorHelper","_n","F","s","next","_slicedToArray","_arrayWithHoles","_iterableToArrayLimit","_nonIterableRest","toString","slice","constructor","name","test","push","_typeof","window","coreAIChatManager","defaultConfig","generatedImageAltText","generatedImageMaxWidth","downloadImageTitle","downloadChartTitle","downloadChartButtonText","userLabel","assistantLabel","thumbsUpTitle","thumbsDownTitle","copyTitle","copiedTitle","codeCopiedText","copyResetDelayMs","widget","chatWidgetContainer","chatWidgetStateName","chatHistorySection","showHistoryButton","closeHistoryButton","newChatButton","toggleButtonSelector","resetSizeButtonSelector","dragHandleSelector","enableDragging","enableResizing","persistLayout","defaultWidth","defaultHeight","minWidth","minHeight","messageTemplate","indicatorTemplate","sanitizeUrl","url","trimmed","trim","escapeHtmlEntities","text","span","document","createElement","textContent","innerHTML","containsFontAwesomePlaceholders","root","nodeType","selector","matches","querySelector","refreshFontAwesomeIcons","fontAwesome","FontAwesome","dom","i2svg","node","observeFontAwesomeIcons","MutationObserver","observer","mutations","forEach","mutation","addedNodes","observe","childList","subtree","parsePixelValue","Number","isFinite","parsed","parseFloat","clamp","min","max","Math","normalizeReference","reference","_ref","_normalized$index","_ref2","_normalized$text","_ref3","_normalized$title","_ref4","_normalized$link","_ref5","_normalized$reference","_normalized$isGenerat","normalized","assign","index","Index","Text","title","Title","link","Link","referenceType","ReferenceType","isGenerated","IsGenerated","isDownloadCitationReference","toLowerCase","normalizeReferences","references","_i","_Object$entries","entries","_normalizeReference","_Object$entries$_i","key","getCitationLabel","buildCitationDisplay","content","processedContent","messageReferences","referenceEntries","citations","citedRefs","filter","_ref6","_ref7","includes","generatedRefs","_ref8","_ref9","sort","_ref0","_ref1","_ref10","_ref11","b","_ref12","_ref13","_ref14","_ref15","displayIndex","_iterator","_step","_step$value","placeholder","concat","replaceAll","referenceKey","label","isDownload","err","_i2","_citations","citation","_iterator2","_step2","_step2$value","map","_ref16","_excluded","buildCopyContent","copyContent","_iterator3","_step3","_iterator4","_step4","trimEnd","updateMessagePresentation","message","rawContent","citationDisplay","displayContent","citationReferences","htmlContent","parseMarkdownContent","renderer","marked","Renderer","data","href","code","lang","highlighted","hljs","getLanguage","highlight","language","_","highlightAuto","langDisplay","image","src","alt","maxWidth","chartCounter","_pendingCharts","__chartConfigs","createChartHtml","chartId","use","extensions","level","start","idx","undefined","tokenizer","extracted","tryExtractChartMarker","startIndex","type","raw","substring","endIndex","json","token","config","jsonStart","depth","inString","escape","ch","jsonEnd","closeBracketIndex","renderChartsInMessage","charts","requestAnimationFrame","_iterator5","_step5","renderChartOnCanvas","canvas","getElementById","Chart","console","warn","offsetParent","_cfg$options","_cfg$options2","_cfg$options2$aspectR","_chartInstance","destroy","cfg","JSON","parse","options","responsive","maintainAspectRatio","aspectRatio","error","renderPendingCharts","configs","_i3","_Object$keys","keys","html","DOMPurify","sanitize","ADD_TAGS","ADD_ATTR","compactObject","source","fromEntries","_ref17","_ref18","resolveIndicatorTemplate","template","encodedAssistantLabel","replace","initialize","instanceConfig","normalizedInstanceConfig","normalizedWidgetConfig","hasWidgetConfig","widgetBehavior","coreAIChatWidgetBehavior","signalRHubUrl","appElementSelector","chatContainerElementSelector","inputElementSelector","sendButtonElementSelector","appDefinition","inputElement","buttonElement","chatContainer","isSessionStarted","isPlaceholderVisible","isStreaming","isNavigatingAway","autoScroll","stream","messages","notifications","prompt","documents","existingDocuments","isUploading","isDocumentOperationPending","documentOperationQueue","uploadErrors","isDragOver","documentBar","metricsEnabled","isRecording","mediaRecorder","preRecordingPrompt","micButton","speechToTextEnabled","chatMode","textToSpeechEnabled","ttsVoiceName","audioChunks","audioPlayQueue","isPlayingAudio","currentAudioElement","currentAudioUrl","ttsButton","ttsPlayingMessageIndex","ttsAudioCache","ttsInstanceId","random","singleResponseMode","conversationModeEnabled","conversationButton","isConversationMode","notificationDismissTimers","pendingSessionPromise","pendingSessionResolver","pendingSessionRejector","pendingSessionTimeoutId","copiedMessageIndex","copyResetTimeoutId","activeCopyButton","computed","lastAssistantIndex","role","methods","handleBeforeUnload","handleDragOver","sessionDocumentsEnabled","preventDefault","stopPropagation","inputArea","closest","classList","add","handleDragLeave","remove","handleDrop","dataTransfer","files","uploadFiles","triggerFileInput","fileInput","click","handleFileInputChange","target","queueDocumentOperation","operation","self","previousOperation","nextOperation","_callee","_context","_this","_callee3","filesToUpload","_context3","uploadDocumentUrl","_callee2","sessionId","profileId","formData","response","errorText","uploadError","result","_t","_t2","_context2","getSessionId","getProfileId","ensureSessionForDocuments","fileName","renderDocumentBar","FormData","append","fetch","method","body","ok","extractReadableErrorMessage","initializeSession","uploaded","failed","reloadCurrentSession","removeDocument","doc","_this2","_callee5","_context5","removeDocumentUrl","_callee4","removeError","_t3","_context4","headers","stringify","itemId","documentId","splice","status","formatFileSize","bytes","toFixed","escapeHtml","failedItem","failedName","errorMsg","supportedExtensionsText","replaceChildren","RETURN_DOM_FRAGMENT","closeButtons","querySelectorAll","j","addEventListener","docToRemove","parseInt","getAttribute","errorCloseButtons","addBtn","div","fallbackMessage","startsWith","detail","normalizeAssistantAppearance","appearance","icon","cssClass","disableStreamingAnimation","getAssistantLabel","getAssistantRoleClasses","classes","getAssistantIconClasses","shouldAnimateAssistantIcon","getAssistantIcon","startConnection","_this3","_callee6","_t4","_context6","connection","signalR","HubConnectionBuilder","withUrl","withAutomaticReconnect","build","serverTimeoutInMilliseconds","keepAliveIntervalInMilliseconds","on","_data$messages","msg","addMessage","$nextTick","refreshAllFeedbackIcons","initialPrompt","sendMessage","stopRecording","handleReceiveError","messageId","userRating","find","id","isFinal","_conversationPartialTranscript","escaped","_conversationPartialMessage","hidePlaceholder","isPartial","scrollToBottom","_audioInputSent","dispatchEvent","Event","stopAudio","_conversationAssistantMessage","oldMsg","responseId","hideTypingIndicator","msgIndex","newMessage","base64Audio","contentType","binaryString","atob","Uint8Array","charCodeAt","playCollectedAudio","notification","receiveNotification","updateNotification","notificationType","removeNotification","onreconnecting","onreconnected","info","onclose","addMessageInternal","_this4","fireEvent","CustomEvent","_this5","_message$rawContent","addMessages","_this6","showPlaceholder","isOrchestratorAvailable","applyOrchestratorAvailability","unavailableMessage","orchestratorUnavailableMessage","disabled","micButtonElement","style","display","conversationButtonElement","event","isIndicator","trimmedPrompt","streamMessage","startRecording","_this7","navigator","mediaDevices","getUserMedia","audio","echoCancellation","noiseSuppression","autoGainControl","mimeType","MediaRecorder","isTypeSupported","audioBitsPerSecond","subject","Subject","pendingChunk","size","_callee7","uint8Array","base64","_context7","arrayBuffer","reduce","str","byte","String","fromCharCode","btoa","getTracks","track","stop","complete","documentElement","send","updateMicButton","toggleRecording","sessionProfileId","_this8","dispose","streamingStarted","showTypingIndicator","lastResponseId","messageIndex","currentSessionId","subscribe","chunk","_i4","_Object$entries2","_normalizeReference2","_Object$entries2$_i","_this8$stream","processReferences","streamingFinished","synthesizeSpeech","_this8$stream2","getServiceDownMessage","_this9","_ref23","_message$rawContent2","stopIcon","setAttribute","startIcon","removeAttribute","focus","icons","handleExternalTtsStop","_e$detail","sourceId","updateTtsPlaybackButtons","_this0","buttons","button","buttonIndex","isPlaying","toggle","updateCopyButtons","_this1","isCopied","iconHtml","setCopyButtonState","cacheIndex","_this10","_ttsCacheIndex","invoke","toggleMessageTts","_this11","playAudioBlob","_this12","totalLength","sum","combined","offset","_iterator6","_step6","set","blob","Blob","_this13","URL","createObjectURL","Audio","revokeObjectURL","playNextInQueue","play","_this14","nextBlob","shift","conversationModeOnAudioEnded","_this15","pause","currentTime","toggleConversationMode","stopConversationMode","startConversationMode","_this16","updateConversationButton","_conversationSubject","_conversationStream","AudioCtx","AudioContext","webkitAudioContext","_conversationAudioCtx","_conversationAnalyser","createAnalyser","fftSize","micSource","createMediaStreamSource","connect","analyser","interruptVolumeThreshold","freqData","frequencyBinCount","getByteFrequencyData","k","avg","_callee8","_context8","close","dismissible","autoDismissMs","endHtml","blur","startHtml","conversationModeSendPrompt","generatePrompt","element","templateProfileId","createSessionUrl","baseUrl","param","fullUrl","location","origin","searchParams","originalLength","removedCount","_this17","clearNotificationDismiss","existingIndex","findIndex","scheduleNotificationDismiss","_this18","setTimeout","timerId","clearTimeout","dismissNotification","handleNotificationAction","actionName","_this19","scrollTop","scrollHeight","clientHeight","handleUserInput","setSessionId","resetSession","rejectPendingSessionRequest","sessionRating","onSessionReset","startNewSession","requestNewSession","_this20","_callee9","_context9","_this21","reject","resolvePendingSessionRequest","clearPendingSessionRequest","initializeApp","_this22","placeholderElementSelector","loadSession","documentBarSelector","className","multiple","allowedExtensions","accept","parentElement","appendChild","threshold","atBottom","shiftKey","lastMsg","pop","promptGenerators","getElementsByClassName","chatSessions","showChatScreen","initialMessages","btn","block","codeEl","clipboard","writeText","copiedText","micButtonElementSelector","conversationButtonElementSelector","force","onSessionInitialized","resolveSessionId","clearCopiedMessageState","copyResponse","_ref25","_message$copyContent","_event$target","_event$target$closest","_this23","currentTarget","updateFeedbackIcons","container","upBtn","downBtn","upClass","upIcon","fontSize","downClass","downIcon","containers","$el","msgId","rateMessage","isPositive","newRating","feedbackContainer","btnClass","offsetWidth","onEnd","removeEventListener","watch","handler","onDocumentsChanged","deep","_this24","active","mounted","_this25","_callee0","isInitialized","_context0","onMounted","fontAwesomeObserver","beforeUnmount","disconnect","onBeforeUnmount","app","Vue","createApp","mount","attach","autoInitializeSelector","getAttributeValue","attributeName","parseBooleanAttributeValue","parseJsonAttribute","description","rawValue","buildConfigFromDataAttributes","_parseJsonAttribute","_parseJsonAttribute2","settings","hasAttribute","allowWidgetHost","booleanAttributes","buildConfigFromElement","jsonConfig","attributeConfig","initializeFromElement","dataset","coreAiChatInitialized","__coreAIChatApp","scanForAutoInitialization","startAutoInitialization","readyState","once","download","toDataURL","img","res","removeChild"],"mappings":"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","file":"ai-chat.js","sourcesContent":["window.coreAIChatManager = function () {\n\n // Defaults (can be overridden by instanceConfig)\n var defaultConfig = {\n // UI defaults for generated media\n generatedImageAltText: 'Generated Image',\n generatedImageMaxWidth: 400,\n downloadImageTitle: 'Download image',\n downloadChartTitle: 'Download chart as image',\n downloadChartButtonText: 'Download',\n userLabel: 'You',\n assistantLabel: 'Assistant',\n thumbsUpTitle: 'Thumbs up',\n thumbsDownTitle: 'Thumbs down',\n copyTitle: 'Click here to copy response to clipboard.',\n copiedTitle: 'Response copied to clipboard.',\n codeCopiedText: 'Copied!',\n copyResetDelayMs: 2000,\n widget: {\n chatWidgetContainer: null,\n chatWidgetStateName: null,\n chatHistorySection: null,\n showHistoryButton: null,\n closeHistoryButton: null,\n newChatButton: null,\n toggleButtonSelector: null,\n resetSizeButtonSelector: null,\n dragHandleSelector: '.ai-chat-widget-header',\n enableDragging: true,\n enableResizing: true,\n persistLayout: true,\n defaultWidth: null,\n defaultHeight: null,\n minWidth: 320,\n minHeight: 420\n },\n messageTemplate: `\n
\n \n
\n
\n \n {{ notification.content }}\n \n
\n
\n \n
\n
\n
\n `,\n indicatorTemplate: `\n
\n
\n \n Assistant\n
\n
\n `\n };\n\n // Sanitize URLs to prevent javascript: protocol injection.\n function sanitizeUrl(url) {\n if (!url) return '';\n var trimmed = url.trim();\n if (/^javascript:/i.test(trimmed) || /^vbscript:/i.test(trimmed) || /^data:text\\/html/i.test(trimmed)) {\n return '';\n }\n return url;\n }\n\n // Safely HTML-encode a string using the DOM (avoids regex-based HTML filtering).\n function escapeHtmlEntities(text) {\n var span = document.createElement('span');\n span.textContent = text;\n return span.innerHTML;\n }\n\n function containsFontAwesomePlaceholders(root) {\n if (!root || root.nodeType !== 1) {\n return false;\n }\n\n var selector = 'i[class*=\"fa-\"],i.fa,i.fas,i.far,i.fab';\n if (typeof root.matches === 'function' && root.matches(selector)) {\n return true;\n }\n\n return typeof root.querySelector === 'function' && !!root.querySelector(selector);\n }\n\n function refreshFontAwesomeIcons(root) {\n var fontAwesome = window.FontAwesome;\n if (!containsFontAwesomePlaceholders(root) || !fontAwesome || !fontAwesome.dom || typeof fontAwesome.dom.i2svg !== 'function') {\n return;\n }\n\n fontAwesome.dom.i2svg({ node: root });\n }\n\n function observeFontAwesomeIcons(root) {\n if (!root || typeof MutationObserver === 'undefined') {\n return null;\n }\n\n var observer = new MutationObserver(function (mutations) {\n mutations.forEach(function (mutation) {\n mutation.addedNodes.forEach(function (node) {\n refreshFontAwesomeIcons(node);\n });\n });\n });\n\n observer.observe(root, {\n childList: true,\n subtree: true\n });\n\n return observer;\n }\n\n function parsePixelValue(value) {\n if (typeof value === 'number' && Number.isFinite(value)) {\n return value;\n }\n\n if (typeof value !== 'string') {\n return null;\n }\n\n var parsed = parseFloat(value);\n return Number.isFinite(parsed) ? parsed : null;\n }\n\n function clamp(value, min, max) {\n return Math.min(Math.max(value, min), max);\n }\n\n function normalizeReference(reference) {\n if (!reference || typeof reference !== 'object') {\n return null;\n }\n\n const normalized = Object.assign({}, reference);\n normalized.index = normalized.index ?? normalized.Index ?? 0;\n normalized.text = normalized.text ?? normalized.Text ?? null;\n normalized.title = normalized.title ?? normalized.Title ?? null;\n normalized.link = sanitizeUrl(normalized.link ?? normalized.Link ?? null);\n normalized.referenceType = normalized.referenceType ?? normalized.ReferenceType ?? null;\n normalized.isGenerated = (normalized.isGenerated ?? normalized.IsGenerated) === true;\n\n return normalized;\n }\n\n function isDownloadCitationReference(reference) {\n if (!reference || typeof reference !== 'object') {\n return false;\n }\n\n if (typeof reference.referenceType === 'string' && reference.referenceType.toLowerCase() === 'document') {\n return true;\n }\n\n if (typeof reference.link === 'string' && /\\/ai\\/documents\\/.+\\/download(?:$|\\?)/i.test(reference.link)) {\n return true;\n }\n\n return false;\n }\n\n function normalizeReferences(references) {\n if (!references || typeof references !== 'object') {\n return {};\n }\n\n const normalized = {};\n\n for (const [key, value] of Object.entries(references)) {\n normalized[key] = normalizeReference(value) ?? {};\n }\n\n return normalized;\n }\n\n function getCitationLabel(reference, key) {\n return reference.title || reference.text || key;\n }\n\n function buildCitationDisplay(content, references) {\n let processedContent = (content || '').trim();\n const messageReferences = normalizeReferences(references);\n const referenceEntries = Object.entries(messageReferences);\n\n if (!referenceEntries.length) {\n return { content: processedContent, citations: [] };\n }\n\n const citedRefs = referenceEntries.filter(([key]) => processedContent.includes(key));\n const generatedRefs = referenceEntries.filter(([key, value]) => value.isGenerated && !processedContent.includes(key));\n\n if (!citedRefs.length && !generatedRefs.length) {\n return { content: processedContent, citations: [] };\n }\n\n citedRefs.sort(([, a], [, b]) => a.index - b.index);\n generatedRefs.sort(([, a], [, b]) => a.index - b.index);\n\n const citations = [];\n let displayIndex = 1;\n\n for (const [key, value] of citedRefs) {\n const placeholder = `__CITE_${displayIndex}_${value.index || displayIndex}__`;\n processedContent = processedContent.replaceAll(key, placeholder);\n citations.push({\n referenceKey: key,\n displayIndex: displayIndex,\n label: getCitationLabel(value, key),\n link: value.link || null,\n isDownload: isDownloadCitationReference(value),\n placeholder: placeholder,\n });\n\n displayIndex++;\n }\n\n for (const citation of citations) {\n processedContent = processedContent.replaceAll(citation.placeholder, `${citation.displayIndex}`);\n }\n\n processedContent = processedContent.replaceAll('
', ',');\n\n // Generated files (such as exported tabular data) are always offered as a download even when\n // the model does not cite them inline, so the user never loses access to the produced file.\n for (const [key, value] of generatedRefs) {\n citations.push({\n referenceKey: key,\n displayIndex: displayIndex,\n label: getCitationLabel(value, key),\n link: value.link || null,\n isDownload: true,\n placeholder: null,\n });\n\n displayIndex++;\n }\n\n return {\n content: processedContent,\n citations: citations.map(({ placeholder, ...citation }) => citation),\n };\n }\n\n function buildCopyContent(content, citations) {\n let copyContent = (content || '').trim();\n\n if (!copyContent || !Array.isArray(citations) || citations.length === 0) {\n return copyContent;\n }\n\n for (const citation of citations) {\n copyContent = copyContent.replaceAll(citation.referenceKey, `[${citation.displayIndex}]`);\n }\n\n copyContent += '\\n\\nReferences:\\n';\n\n for (const citation of citations) {\n copyContent += `${citation.displayIndex}. ${citation.label}`;\n\n if (citation.link) {\n copyContent += ` - ${citation.link}`;\n }\n\n copyContent += '\\n';\n }\n\n return copyContent.trimEnd();\n }\n\n function updateMessagePresentation(message, references) {\n const messageReferences = normalizeReferences(references ?? message.references);\n const rawContent = typeof message.rawContent === 'string'\n ? message.rawContent\n : typeof message.content === 'string'\n ? message.content\n : '';\n const citationDisplay = buildCitationDisplay(rawContent, messageReferences);\n\n message.rawContent = rawContent;\n message.content = rawContent;\n message.displayContent = citationDisplay.content;\n message.references = messageReferences;\n message.citationReferences = citationDisplay.citations;\n message.copyContent = buildCopyContent(rawContent, citationDisplay.citations);\n message.htmlContent = parseMarkdownContent(citationDisplay.content, message);\n\n return message;\n }\n\n const renderer = new marked.Renderer();\n\n // Modify the link rendering to open in a new tab\n renderer.link = function (data) {\n var href = sanitizeUrl(data.href);\n if (!href) return data.text || '';\n return `${data.text}`;\n };\n\n // Custom code block renderer with highlight.js integration and copy button.\n renderer.code = function (data) {\n var code = data.text || '';\n var lang = (data.lang || '').trim();\n var highlighted = code;\n\n if (typeof hljs !== 'undefined') {\n if (lang && hljs.getLanguage(lang)) {\n try {\n highlighted = hljs.highlight(code, { language: lang }).value;\n } catch (_) { }\n } else {\n try {\n highlighted = hljs.highlightAuto(code).value;\n } catch (_) { }\n }\n } else {\n highlighted = escapeHtmlEntities(code);\n }\n\n var langDisplay = lang ? escapeHtmlEntities(lang) : 'code';\n return `
${langDisplay}
${highlighted}
`;\n };\n\n // Custom image renderer for generated images with thumbnail styling and download button.\n // Handles both URL and data-URI sources (data URIs are converted to blobs for download).\n renderer.image = function (data) {\n const src = sanitizeUrl(data.href);\n if (!src) return '';\n const alt = data.text || defaultConfig.generatedImageAltText;\n const maxWidth = defaultConfig.generatedImageMaxWidth;\n return `
\n \"${alt}\"\n
\n \n \n \n
\n
`;\n };\n\n // Chart counter for unique IDs\n let chartCounter = 0;\n\n // Collector for charts discovered during marked parsing.\n let _pendingCharts = [];\n\n // Global chart config map: any page (e.g., Chat Interactions) that uses\n // the shared marked instance can call window.renderPendingCharts() after\n // its DOM update to render charts it didn't create itself.\n window.__chartConfigs = window.__chartConfigs || {};\n\n function createChartHtml(chartId) {\n return `
`\n + ``\n + `
`\n + `
`\n + ``\n + `
`;\n }\n\n // Register [chart:{...json...}] as a native marked block extension so the\n // markdown parser handles chart markers inline with surrounding text.\n marked.use({\n extensions: [{\n name: 'chart',\n level: 'block',\n start(src) {\n const idx = src.indexOf('[chart:');\n return idx >= 0 ? idx : undefined;\n },\n tokenizer(src) {\n const extracted = tryExtractChartMarker(src);\n if (!extracted || extracted.startIndex !== 0) {\n return undefined;\n }\n\n const chartId = `chat_chart_${++chartCounter}`;\n\n return {\n type: 'chart',\n raw: src.substring(0, extracted.endIndex),\n chartId: chartId,\n json: extracted.json,\n };\n },\n renderer(token) {\n _pendingCharts.push({ chartId: token.chartId, config: token.json });\n window.__chartConfigs[token.chartId] = token.json;\n return createChartHtml(token.chartId);\n }\n }]\n });\n\n // Extract a [chart:{...json...}] marker. This avoids regex issues with nested brackets.\n function tryExtractChartMarker(text) {\n const token = '[chart:';\n const start = text.indexOf(token);\n if (start < 0) {\n return null;\n }\n\n // Find JSON object boundary by balancing braces\n const jsonStart = start + token.length;\n let i = jsonStart;\n while (i < text.length && (text[i] === ' ' || text[i] === '\\n' || text[i] === '\\r' || text[i] === '\\t')) {\n i++;\n }\n\n if (i >= text.length || text[i] !== '{') {\n return null;\n }\n\n let depth = 0;\n let inString = false;\n let escape = false;\n\n for (; i < text.length; i++) {\n const ch = text[i];\n\n if (inString) {\n if (escape) {\n escape = false;\n continue;\n }\n if (ch === '\\\\') {\n escape = true;\n continue;\n }\n if (ch === '\"') {\n inString = false;\n }\n continue;\n }\n\n if (ch === '\"') {\n inString = true;\n continue;\n }\n\n if (ch === '{') {\n depth++;\n } else if (ch === '}') {\n depth--;\n if (depth === 0) {\n const jsonEnd = i;\n // Expect closing bracket after JSON\n const closeBracketIndex = text.indexOf(']', jsonEnd + 1);\n if (closeBracketIndex < 0) {\n return null;\n }\n\n const json = text.substring(jsonStart, jsonEnd + 1).trim();\n return {\n startIndex: start,\n endIndex: closeBracketIndex + 1,\n json: json\n };\n }\n }\n }\n\n return null;\n }\n\n function renderChartsInMessage(message) {\n if (!message || !message._pendingCharts || !message._pendingCharts.length) {\n return;\n }\n\n // Copy and clear pending charts immediately to prevent duplicate renders.\n const charts = [...message._pendingCharts];\n message._pendingCharts = [];\n\n // Defer to requestAnimationFrame so the browser has fully laid out the\n // canvas elements before Chart.js reads their dimensions.\n requestAnimationFrame(() => {\n for (const c of charts) {\n renderChartOnCanvas(c.chartId, c.config);\n }\n });\n }\n\n function renderChartOnCanvas(chartId, config) {\n const canvas = document.getElementById(chartId);\n if (!canvas) {\n return false;\n }\n\n if (typeof Chart === 'undefined') {\n console.warn('Chart.js is not loaded. To render interactive charts, include the Chart.js library on the page (e.g., ).');\n return false;\n }\n\n // When the canvas is inside a hidden container (e.g., a widget panel with\n // display:none), it has zero dimensions and Chart.js cannot render correctly.\n // Keep the config in __chartConfigs so renderPendingCharts() can retry later\n // once the container becomes visible.\n if (canvas.offsetParent === null) {\n window.__chartConfigs[chartId] = config;\n return false;\n }\n\n try {\n if (canvas._chartInstance) {\n canvas._chartInstance.destroy();\n }\n\n const cfg = typeof config === 'string' ? JSON.parse(config) : config;\n cfg.options ??= {};\n cfg.options.responsive = true;\n cfg.options.maintainAspectRatio = true;\n cfg.options.aspectRatio ??= 4 / 3;\n\n canvas._chartInstance = new Chart(canvas, cfg);\n delete window.__chartConfigs[chartId];\n return true;\n } catch (e) {\n console.error('Error creating chart:', e);\n return false;\n }\n }\n\n // Global function: renders any chart canvases whose configs are in the\n // global __chartConfigs map. Called by pages (e.g., Chat Interactions)\n // that share the marked instance but have their own rendering pipeline.\n window.renderPendingCharts = function () {\n if (typeof Chart === 'undefined') {\n return;\n }\n\n const configs = window.__chartConfigs;\n if (!configs) {\n return;\n }\n\n requestAnimationFrame(() => {\n for (const chartId of Object.keys(configs)) {\n renderChartOnCanvas(chartId, configs[chartId]);\n }\n });\n };\n\n // Parse markdown content via marked (which natively handles [chart:...] markers\n // through the registered extension) and collect pending chart configs for later\n // Chart.js rendering.\n function parseMarkdownContent(content, message) {\n _pendingCharts = [];\n const html = marked.parse(content, { renderer });\n message._pendingCharts = _pendingCharts.length > 0 ? [..._pendingCharts] : [];\n return DOMPurify.sanitize(html, { ADD_TAGS: ['canvas'], ADD_ATTR: ['target'] });\n }\n\n function compactObject(source) {\n if (!source || typeof source !== 'object') {\n return {};\n }\n\n return Object.fromEntries(\n Object.entries(source).filter(([, value]) => value !== undefined)\n );\n }\n\n function resolveIndicatorTemplate(template, assistantLabel) {\n if (!template) {\n return template;\n }\n\n const encodedAssistantLabel = escapeHtmlEntities(assistantLabel || 'Assistant');\n return template.replace(/\\{\\{\\s*assistantLabel\\s*\\}\\}/g, encodedAssistantLabel);\n }\n\n const initialize = (instanceConfig) => {\n const normalizedInstanceConfig = compactObject(instanceConfig);\n const normalizedWidgetConfig = compactObject(normalizedInstanceConfig.widget);\n const config = Object.assign({}, defaultConfig, normalizedInstanceConfig);\n config.widget = Object.assign({}, defaultConfig.widget || {}, normalizedWidgetConfig);\n config.indicatorTemplate = resolveIndicatorTemplate(config.indicatorTemplate, config.assistantLabel);\n const hasWidgetConfig = !!(normalizedWidgetConfig.chatWidgetContainer && normalizedWidgetConfig.chatWidgetStateName);\n const widgetBehavior = window.coreAIChatWidgetBehavior || null;\n // Keep defaultConfig in sync so renderers use overridden values\n defaultConfig = config;\n\n if (!config.signalRHubUrl) {\n console.error('The signalRHubUrl is required.');\n return;\n }\n\n if (!config.appElementSelector) {\n console.error('The appElementSelector is required.');\n return;\n }\n\n if (!config.chatContainerElementSelector) {\n console.error('The chatContainerElementSelector is required.');\n return;\n }\n\n if (!config.inputElementSelector) {\n console.error('The inputElementSelector is required.');\n return;\n }\n\n if (!config.sendButtonElementSelector) {\n console.error('The sendButtonElementSelector is required.');\n return;\n }\n\n const appDefinition = {\n data() {\n return {\n inputElement: null,\n buttonElement: null,\n chatContainer: null,\n placeholder: null,\n isSessionStarted: false,\n isPlaceholderVisible: true,\n isStreaming: false,\n isNavigatingAway: false,\n autoScroll: true,\n stream: null,\n messages: [],\n notifications: [],\n prompt: '',\n documents: config.existingDocuments || [],\n isUploading: false,\n isDocumentOperationPending: false,\n documentOperationQueue: null,\n uploadErrors: [],\n isDragOver: false,\n documentBar: null,\n metricsEnabled: !!config.metricsEnabled,\n userLabel: config.userLabel,\n assistantLabel: config.assistantLabel,\n thumbsUpTitle: config.thumbsUpTitle,\n thumbsDownTitle: config.thumbsDownTitle,\n copyTitle: config.copyTitle,\n copiedTitle: config.copiedTitle,\n isRecording: false,\n mediaRecorder: null,\n preRecordingPrompt: '',\n micButton: null,\n speechToTextEnabled: config.chatMode === 'AudioInput' || config.chatMode === 'Conversation',\n textToSpeechEnabled: config.chatMode === 'Conversation' || !!config.textToSpeechEnabled,\n ttsVoiceName: config.ttsVoiceName || null,\n audioChunks: [],\n audioPlayQueue: [],\n isPlayingAudio: false,\n currentAudioElement: null,\n currentAudioUrl: null,\n ttsButton: null,\n ttsPlayingMessageIndex: -1,\n ttsAudioCache: {},\n ttsInstanceId: 'ai-chat-' + Math.random().toString(36).slice(2),\n singleResponseMode: !!config.singleResponseMode,\n conversationModeEnabled: config.chatMode === 'Conversation',\n conversationButton: null,\n isConversationMode: false,\n notificationDismissTimers: {},\n pendingSessionPromise: null,\n pendingSessionResolver: null,\n pendingSessionRejector: null,\n pendingSessionTimeoutId: null,\n copiedMessageIndex: -1,\n copyResetTimeoutId: null,\n activeCopyButton: null,\n };\n },\n computed: {\n lastAssistantIndex() {\n for (var i = this.messages.length - 1; i >= 0; i--) {\n if (this.messages[i].role === 'assistant') {\n return i;\n }\n }\n return -1;\n }\n },\n methods: {\n handleBeforeUnload() {\n this.isNavigatingAway = true;\n },\n handleDragOver(e) {\n if (!config.sessionDocumentsEnabled) return;\n e.preventDefault();\n e.stopPropagation();\n this.isDragOver = true;\n var inputArea = this.inputElement ? this.inputElement.closest('.ai-admin-widget-input, .text-bg-light') : null;\n if (inputArea) inputArea.classList.add('ai-chat-drag-over');\n },\n handleDragLeave(e) {\n if (!config.sessionDocumentsEnabled) return;\n e.preventDefault();\n e.stopPropagation();\n this.isDragOver = false;\n var inputArea = this.inputElement ? this.inputElement.closest('.ai-admin-widget-input, .text-bg-light') : null;\n if (inputArea) inputArea.classList.remove('ai-chat-drag-over');\n },\n handleDrop(e) {\n if (!config.sessionDocumentsEnabled) return;\n e.preventDefault();\n e.stopPropagation();\n this.isDragOver = false;\n var inputArea = this.inputElement ? this.inputElement.closest('.ai-admin-widget-input, .text-bg-light') : null;\n if (inputArea) inputArea.classList.remove('ai-chat-drag-over');\n if (e.dataTransfer && e.dataTransfer.files && e.dataTransfer.files.length > 0) {\n this.uploadFiles(Array.from(e.dataTransfer.files));\n }\n },\n triggerFileInput() {\n if (!config.sessionDocumentsEnabled || this.isDocumentOperationPending) return;\n var fileInput = document.getElementById('ai-chat-doc-input');\n if (fileInput) fileInput.click();\n },\n handleFileInputChange(e) {\n var files = e.target.files ? Array.from(e.target.files) : [];\n if (files && files.length > 0) {\n this.uploadFiles(files);\n }\n e.target.value = '';\n },\n queueDocumentOperation(operation) {\n var self = this;\n var previousOperation = this.documentOperationQueue || Promise.resolve();\n var nextOperation = previousOperation\n .catch(function () { })\n .then(async function () {\n self.isDocumentOperationPending = true;\n try {\n return await operation();\n } finally {\n self.isDocumentOperationPending = false;\n }\n });\n\n this.documentOperationQueue = nextOperation.finally(function () {\n if (self.documentOperationQueue === nextOperation) {\n self.documentOperationQueue = null;\n }\n });\n\n return this.documentOperationQueue;\n },\n async uploadFiles(files) {\n if (!config.uploadDocumentUrl) return;\n\n var filesToUpload = Array.isArray(files) ? files.slice() : Array.from(files || []);\n if (filesToUpload.length === 0) return;\n\n return this.queueDocumentOperation(async () => {\n var sessionId = this.getSessionId();\n var profileId = this.getProfileId();\n\n if (!sessionId) {\n try {\n sessionId = await this.ensureSessionForDocuments(profileId);\n } catch (err) {\n console.error('Failed to create a chat session for document upload:', err);\n this.uploadErrors = [{ fileName: '', error: 'Could not create a chat session for the upload.' }];\n this.renderDocumentBar();\n return;\n }\n }\n\n if (!sessionId) {\n console.warn('Cannot upload documents without a session or profile.');\n this.uploadErrors = [{ fileName: '', error: 'Could not create a chat session for the upload.' }];\n this.renderDocumentBar();\n return;\n }\n\n this.isUploading = true;\n this.uploadErrors = [];\n this.renderDocumentBar();\n try {\n var formData = new FormData();\n formData.append('sessionId', sessionId);\n for (var i = 0; i < filesToUpload.length; i++) {\n formData.append('files', filesToUpload[i]);\n }\n\n var response = await fetch(config.uploadDocumentUrl, {\n method: 'POST',\n body: formData\n });\n\n if (!response.ok) {\n var errorText = await response.text();\n var uploadError = this.extractReadableErrorMessage(errorText, 'Upload failed. Please try again.');\n console.error('Upload failed:', errorText);\n this.uploadErrors = [{ fileName: '', error: uploadError }];\n return;\n }\n\n var result = await response.json();\n\n if (result.sessionId && result.sessionId !== this.getSessionId()) {\n this.initializeSession(result.sessionId);\n }\n\n if (Array.isArray(result.documents)) {\n this.documents = result.documents;\n } else if (result.uploaded && result.uploaded.length > 0) {\n this.documents = this.documents.concat(result.uploaded);\n }\n\n if (result.failed && result.failed.length > 0) {\n this.uploadErrors = result.failed;\n }\n } catch (err) {\n console.error('Upload error:', err);\n this.uploadErrors = [{ fileName: '', error: 'Upload failed. Please try again.' }];\n\n if (this.getSessionId()) {\n this.reloadCurrentSession();\n }\n } finally {\n this.isUploading = false;\n this.renderDocumentBar();\n }\n });\n },\n async removeDocument(doc) {\n if (!config.removeDocumentUrl) return;\n\n return this.queueDocumentOperation(async () => {\n try {\n var sessionId = this.getSessionId();\n var response = await fetch(config.removeDocumentUrl, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ itemId: sessionId, documentId: doc.documentId })\n });\n\n if (response.ok) {\n var result = await response.json();\n\n if (Array.isArray(result.documents)) {\n this.documents = result.documents;\n } else {\n var idx = this.documents.indexOf(doc);\n if (idx > -1) {\n this.documents.splice(idx, 1);\n }\n }\n } else {\n var errorText = await response.text();\n var removeError = this.extractReadableErrorMessage(errorText, 'Failed to remove document. Please try again.');\n console.error('Failed to remove document:', response.status, errorText);\n this.uploadErrors = [{ fileName: doc.fileName || '', error: removeError }];\n if (sessionId) {\n this.reloadCurrentSession();\n }\n this.renderDocumentBar();\n }\n } catch (err) {\n console.error('Remove document error:', err);\n this.uploadErrors = [{ fileName: doc.fileName || '', error: 'Failed to remove document. Please try again.' }];\n if (this.getSessionId()) {\n this.reloadCurrentSession();\n }\n this.renderDocumentBar();\n }\n });\n },\n formatFileSize(bytes) {\n if (bytes < 1024) return bytes + ' B';\n if (bytes < 1024 * 1024) return (bytes / 1024).toFixed(1) + ' KB';\n return (bytes / (1024 * 1024)).toFixed(1) + ' MB';\n },\n renderDocumentBar() {\n if (!this.documentBar) return;\n\n if (!config.sessionDocumentsEnabled) {\n this.documentBar.classList.add('d-none');\n return;\n }\n\n this.documentBar.classList.remove('d-none');\n\n var html = '
';\n html += '
';\n\n for (var i = 0; i < this.documents.length; i++) {\n var doc = this.documents[i];\n var name = doc.fileName || 'Document';\n if (name.length > 20) name = name.substring(0, 17) + '...';\n html += '';\n html += ' ';\n html += this.escapeHtml(name);\n html += ' ';\n html += '';\n }\n\n for (var m = 0; m < this.uploadErrors.length; m++) {\n var failedItem = this.uploadErrors[m];\n var failedName = failedItem.fileName || 'File';\n var errorMsg = failedItem.error || 'Upload failed';\n if (failedName.length > 15) failedName = failedName.substring(0, 12) + '...';\n html += '';\n html += ' ';\n html += this.escapeHtml(failedName);\n html += ' ';\n html += '';\n }\n\n if (this.isUploading) {\n html += '';\n html += ' Uploading...';\n html += '';\n }\n\n html += '';\n html += '
';\n if (config.supportedExtensionsText) {\n html += '
Supported formats: ' + this.escapeHtml(config.supportedExtensionsText) + '
';\n }\n\n html += '
';\n\n this.documentBar.replaceChildren(DOMPurify.sanitize(html, { RETURN_DOM_FRAGMENT: true }));\n\n // Bind remove handlers\n var self = this;\n var closeButtons = this.documentBar.querySelectorAll('[data-doc-index]');\n for (var j = 0; j < closeButtons.length; j++) {\n closeButtons[j].addEventListener('click', (function (idx) {\n return function (e) {\n e.preventDefault();\n e.stopPropagation();\n if (self.isDocumentOperationPending) {\n return;\n }\n\n var docToRemove = self.documents[idx];\n if (docToRemove) self.removeDocument(docToRemove);\n };\n })(parseInt(closeButtons[j].getAttribute('data-doc-index'))));\n }\n\n // Bind error dismiss handlers\n var errorCloseButtons = this.documentBar.querySelectorAll('[data-error-index]');\n for (var n = 0; n < errorCloseButtons.length; n++) {\n errorCloseButtons[n].addEventListener('click', (function (idx) {\n return function (e) {\n e.preventDefault();\n e.stopPropagation();\n self.uploadErrors.splice(idx, 1);\n self.renderDocumentBar();\n };\n })(parseInt(errorCloseButtons[n].getAttribute('data-error-index'))));\n }\n\n // Bind add button\n var addBtn = this.documentBar.querySelector('.ai-chat-doc-add-btn');\n if (addBtn) {\n addBtn.addEventListener('click', function (e) {\n e.preventDefault();\n if (self.isDocumentOperationPending) {\n return;\n }\n self.triggerFileInput();\n });\n }\n },\n escapeHtml(text) {\n var div = document.createElement('div');\n div.textContent = text;\n return div.innerHTML;\n },\n extractReadableErrorMessage(errorText, fallbackMessage) {\n if (!errorText || typeof errorText !== 'string') {\n return fallbackMessage;\n }\n\n var trimmed = errorText.trim();\n if (!trimmed) {\n return fallbackMessage;\n }\n\n if (trimmed.startsWith('{') || trimmed.startsWith('[')) {\n try {\n var parsed = JSON.parse(trimmed);\n var message = parsed?.error || parsed?.message || parsed?.title || parsed?.detail;\n return typeof message === 'string' && message.trim()\n ? message.trim()\n : fallbackMessage;\n } catch (err) {\n return fallbackMessage;\n }\n }\n\n if (/<[^>]+>/.test(trimmed)) {\n return fallbackMessage;\n }\n\n return trimmed;\n },\n normalizeAssistantAppearance(appearance) {\n if (!appearance) {\n return null;\n }\n\n var label = typeof appearance.label === 'string' ? appearance.label.trim() : '';\n var icon = typeof appearance.icon === 'string' ? appearance.icon.trim() : '';\n var cssClass = typeof appearance.cssClass === 'string' ? appearance.cssClass.trim() : '';\n var disableStreamingAnimation = !!appearance.disableStreamingAnimation;\n\n if (!label && !icon && !cssClass && !disableStreamingAnimation) {\n return null;\n }\n\n return {\n label: label,\n icon: icon,\n cssClass: cssClass,\n disableStreamingAnimation: disableStreamingAnimation,\n };\n },\n getAssistantLabel(message) {\n var appearance = message ? this.normalizeAssistantAppearance(message.appearance) : null;\n return appearance && appearance.label ? appearance.label : this.assistantLabel;\n },\n getAssistantRoleClasses(message) {\n var appearance = message ? this.normalizeAssistantAppearance(message.appearance) : null;\n var classes = ['ai-chat-msg-role'];\n\n if (appearance && appearance.cssClass) {\n classes.push(appearance.cssClass);\n } else {\n classes.push('ai-chat-msg-role-assistant');\n }\n\n return classes;\n },\n getAssistantIconClasses(message, index) {\n var appearance = message ? this.normalizeAssistantAppearance(message.appearance) : null;\n return [this.shouldAnimateAssistantIcon(message, index) ? 'ai-streaming-icon' : 'ai-bot-icon', appearance && appearance.cssClass ? appearance.cssClass : ''];\n },\n getAssistantIcon(message) {\n var appearance = message ? this.normalizeAssistantAppearance(message.appearance) : null;\n return appearance && appearance.icon ? appearance.icon : 'fa fa-robot';\n },\n shouldAnimateAssistantIcon(message, index) {\n var appearance = message ? this.normalizeAssistantAppearance(message.appearance) : null;\n return !!message &&\n message.isStreaming &&\n index === this.lastAssistantIndex &&\n !(appearance && appearance.disableStreamingAnimation);\n },\n async startConnection() {\n this.connection = new signalR.HubConnectionBuilder()\n .withUrl(config.signalRHubUrl)\n .withAutomaticReconnect()\n .build();\n\n // Allow long-running operations (e.g., multi-step MCP tool calls)\n // without the client disconnecting prematurely.\n this.connection.serverTimeoutInMilliseconds = 600000;\n this.connection.keepAliveIntervalInMilliseconds = 15000;\n\n this.connection.on(\"LoadSession\", (data) => {\n this.initializeSession(data.sessionId, true);\n this.messages = [];\n this.documents = data.documents || [];\n this.uploadErrors = [];\n\n (data.messages ?? []).forEach(msg => {\n this.addMessage(msg);\n\n this.$nextTick(() => {\n renderChartsInMessage(msg);\n });\n });\n\n // Update feedback icons in the DOM after all messages have rendered.\n this.$nextTick(() => {\n this.refreshAllFeedbackIcons();\n });\n\n // When the session is new (no messages) and an initial prompt is configured,\n // automatically send it as the first user message to trigger an AI response.\n if (this.messages.length === 0 && config.initialPrompt) {\n this.prompt = config.initialPrompt;\n this.sendMessage();\n }\n });\n\n this.connection.on(\"ReceiveError\", (error) => {\n console.error(\"SignalR Error: \", error);\n\n if (this.isRecording) {\n this.stopRecording();\n }\n\n if (widgetBehavior && typeof widgetBehavior.handleReceiveError === 'function') {\n widgetBehavior.handleReceiveError(this, error, config);\n }\n });\n\n this.connection.on(\"MessageRated\", (messageId, userRating) => {\n var msg = this.messages.find(m => m.id === messageId);\n if (msg) {\n msg.userRating = userRating;\n }\n });\n\n this.connection.on(\"ReceiveTranscript\", (sessionId, text, isFinal) => {\n if (this.isConversationMode) {\n if (!isFinal && text) {\n this._conversationPartialTranscript = text;\n var escaped = text.replace(/&/g, '&').replace(//g, '>');\n var html = '

' + escaped + '

';\n\n // Show partial transcript as a live user message.\n if (!this._conversationPartialMessage) {\n this.hidePlaceholder();\n this._conversationPartialMessage = {\n role: 'user',\n content: text,\n htmlContent: html,\n isPartial: true\n };\n this.messages.push(this._conversationPartialMessage);\n } else {\n this._conversationPartialMessage.content = text;\n this._conversationPartialMessage.htmlContent = html;\n }\n this.scrollToBottom();\n }\n return;\n }\n\n if (text && !this._audioInputSent) {\n this.prompt = this.preRecordingPrompt + text;\n if (this.inputElement) {\n this.inputElement.value = this.prompt;\n this.inputElement.dispatchEvent(new Event('input'));\n }\n }\n });\n\n this.connection.on(\"ReceiveConversationUserMessage\", (sessionId, text) => {\n if (text) {\n this.stopAudio();\n\n // If there's an interrupted assistant message still streaming,\n // mark it as done to stop the spinner animation.\n if (this._conversationAssistantMessage) {\n var oldMsg = this.messages[this._conversationAssistantMessage.index];\n if (oldMsg) {\n oldMsg.isStreaming = false;\n }\n this._conversationAssistantMessage = null;\n }\n\n // Replace the partial transcript message with the final one.\n if (this._conversationPartialMessage) {\n var escaped = text.replace(/&/g, '&').replace(//g, '>');\n this._conversationPartialMessage.content = text;\n this._conversationPartialMessage.htmlContent = '

' + escaped + '

';\n this._conversationPartialMessage.isPartial = false;\n this._conversationPartialMessage = null;\n } else {\n this.addMessage({\n role: 'user',\n content: text\n });\n }\n this.scrollToBottom();\n }\n });\n\n this.connection.on(\"ReceiveConversationAssistantToken\", (sessionId, messageId, token, responseId, references, appearance) => {\n if (!this._conversationAssistantMessage) {\n this.stopAudio();\n this.hideTypingIndicator();\n\n // Ensure no stale streaming indicators remain from prior messages.\n for (var j = 0; j < this.messages.length; j++) {\n if (this.messages[j].isStreaming) {\n this.messages[j].isStreaming = false;\n }\n }\n\n var msgIndex = this.messages.length;\n var newMessage = {\n id: messageId,\n role: \"assistant\",\n content: \"\",\n htmlContent: \"\",\n isStreaming: true,\n userRating: null,\n appearance: this.normalizeAssistantAppearance(appearance),\n references: {},\n };\n this.messages.push(newMessage);\n this._conversationAssistantMessage = { index: msgIndex, content: '' };\n }\n\n this._conversationAssistantMessage.content += token;\n var msg = this.messages[this._conversationAssistantMessage.index];\n if (msg) {\n if (!msg.appearance) {\n msg.appearance = this.normalizeAssistantAppearance(appearance);\n }\n msg.rawContent = this._conversationAssistantMessage.content;\n msg.references = normalizeReferences(Object.assign({}, msg.references || {}, references || {}));\n updateMessagePresentation(msg, msg.references);\n this.$nextTick(() => {\n renderChartsInMessage(msg);\n this.scrollToBottom();\n });\n }\n });\n\n this.connection.on(\"ReceiveConversationAssistantComplete\", (sessionId, messageId, references) => {\n if (this._conversationAssistantMessage) {\n var msg = this.messages[this._conversationAssistantMessage.index];\n if (msg) {\n msg.isStreaming = false;\n msg.references = normalizeReferences(Object.assign({}, msg.references || {}, references || {}));\n updateMessagePresentation(msg, msg.references);\n }\n this._conversationAssistantMessage = null;\n }\n });\n\n this.connection.on(\"ReceiveAudioChunk\", (sessionId, base64Audio, contentType) => {\n if (base64Audio) {\n const binaryString = atob(base64Audio);\n const bytes = new Uint8Array(binaryString.length);\n for (let i = 0; i < binaryString.length; i++) {\n bytes[i] = binaryString.charCodeAt(i);\n }\n this.audioChunks.push(bytes);\n }\n });\n\n this.connection.on(\"ReceiveAudioComplete\", (sessionId) => {\n this.playCollectedAudio();\n });\n\n this.connection.on(\"ReceiveNotification\", (notification) => {\n this.receiveNotification(notification);\n });\n\n this.connection.on(\"UpdateNotification\", (notification) => {\n this.updateNotification(notification);\n });\n\n this.connection.on(\"RemoveNotification\", (notificationType) => {\n this.removeNotification(notificationType);\n });\n\n this.connection.onreconnecting(() => {\n console.warn(\"SignalR: reconnecting...\");\n });\n\n this.connection.onreconnected(() => {\n console.info(\"SignalR: reconnected.\");\n\n if (this.isSessionStarted) {\n this.reloadCurrentSession();\n }\n });\n\n this.connection.onclose((error) => {\n if (this.isNavigatingAway) {\n return;\n }\n\n if (error) {\n console.warn(\"SignalR connection closed with error:\", error.message || error);\n }\n });\n\n try {\n await this.connection.start();\n } catch (err) {\n console.error(\"SignalR Connection Error: \", err);\n }\n },\n addMessageInternal(message) {\n if (message.role === 'assistant') {\n message.appearance = this.normalizeAssistantAppearance(message.appearance);\n }\n\n if (message.content && !message.htmlContent) {\n message.htmlContent = parseMarkdownContent(message.content, message);\n }\n this.fireEvent(new CustomEvent(\"addingCoreAIPromotMessage\", { detail: { message: message } }));\n this.messages.push(message);\n\n this.$nextTick(() => {\n this.fireEvent(new CustomEvent(\"addedCoreAIPromotMessage\", { detail: { message: message } }));\n });\n },\n addMessage(message) {\n\n // Ensure userRating is always defined for Vue reactivity.\n if (message.userRating === undefined) {\n message.userRating = null;\n }\n\n if (message.content) {\n message.rawContent = message.rawContent ?? message.content;\n updateMessagePresentation(message, message.references);\n }\n\n this.addMessageInternal(message);\n this.hidePlaceholder();\n\n this.$nextTick(() => {\n // Render any pending charts once the DOM is updated\n renderChartsInMessage(message);\n this.scrollToBottom();\n });\n },\n addMessages(messages) {\n\n for (let i = 0; i < messages.length; i++) {\n this.addMessageInternal(messages[i]);\n }\n\n this.hidePlaceholder();\n this.$nextTick(() => {\n this.scrollToBottom();\n });\n },\n hidePlaceholder() {\n if (this.placeholder) {\n this.placeholder.classList.add('d-none');\n }\n this.isPlaceholderVisible = false;\n },\n showPlaceholder() {\n if (this.placeholder) {\n this.placeholder.classList.remove('d-none');\n }\n this.isPlaceholderVisible = true;\n },\n isOrchestratorAvailable() {\n return config.isOrchestratorAvailable !== false;\n },\n applyOrchestratorAvailability() {\n if (this.isOrchestratorAvailable()) {\n return true;\n }\n\n const unavailableMessage = config.orchestratorUnavailableMessage || \"This orchestrator is not currently available.\";\n\n if (this.inputElement) {\n this.inputElement.disabled = true;\n this.inputElement.value = '';\n this.inputElement.placeholder = unavailableMessage;\n }\n\n if (this.buttonElement) {\n this.buttonElement.disabled = true;\n }\n\n if (this.micButtonElement) {\n this.micButtonElement.disabled = true;\n this.micButtonElement.style.display = 'none';\n }\n\n if (this.conversationButtonElement) {\n this.conversationButtonElement.disabled = true;\n this.conversationButtonElement.style.display = 'none';\n }\n\n return false;\n },\n fireEvent(event) {\n document.dispatchEvent(event);\n },\n isIndicator(message) {\n return message.role === 'indicator';\n },\n sendMessage() {\n if (!this.applyOrchestratorAvailability()) {\n return;\n }\n\n let trimmedPrompt = this.prompt.trim();\n\n if (!trimmedPrompt) {\n return;\n }\n\n // Stop any active recording before sending.\n if (this.isRecording) {\n this.stopRecording();\n }\n\n // Prevent stale ReceiveTranscript events from repopulating the prompt.\n this._audioInputSent = true;\n\n // In single-response mode, clear all previous messages.\n if (this.singleResponseMode) {\n this.messages.splice(0, this.messages.length);\n }\n\n this.addMessage({\n role: 'user',\n content: trimmedPrompt\n });\n\n this.streamMessage(this.getProfileId(), trimmedPrompt, null);\n this.inputElement.value = '';\n this.prompt = '';\n },\n startRecording() {\n if (this.isRecording || !this.connection) {\n return;\n }\n\n navigator.mediaDevices.getUserMedia({ audio: { echoCancellation: true, noiseSuppression: true, autoGainControl: true } })\n .then(stream => {\n var mimeType = MediaRecorder.isTypeSupported('audio/ogg;codecs=opus')\n ? 'audio/ogg;codecs=opus'\n : MediaRecorder.isTypeSupported('audio/webm;codecs=opus')\n ? 'audio/webm;codecs=opus'\n : 'audio/webm';\n\n this.mediaRecorder = new MediaRecorder(stream, {\n mimeType: mimeType,\n audioBitsPerSecond: 128000,\n });\n\n this.preRecordingPrompt = this.prompt;\n this._audioInputSent = false;\n\n var subject = new signalR.Subject();\n var profileId = this.getProfileId();\n var sessionId = this.getSessionId() || '';\n var pendingChunk = Promise.resolve();\n\n this.mediaRecorder.addEventListener('dataavailable', (e) => {\n if (e.data && e.data.size > 0) {\n pendingChunk = pendingChunk.then(async () => {\n var data = await e.data.arrayBuffer();\n var uint8Array = new Uint8Array(data);\n var binaryString = uint8Array.reduce(function (str, byte) { return str + String.fromCharCode(byte); }, '');\n var base64 = btoa(binaryString);\n subject.next(base64);\n });\n }\n });\n\n this.mediaRecorder.addEventListener('stop', () => {\n stream.getTracks().forEach(track => track.stop());\n pendingChunk.then(() => subject.complete());\n });\n\n var language = navigator.language || document.documentElement.lang || 'en-US';\n this.connection.send(\"SendAudioStream\", profileId, sessionId, subject, mimeType, language);\n this.mediaRecorder.start(250);\n this.isRecording = true;\n this.updateMicButton();\n })\n .catch(err => {\n console.error('Microphone access denied:', err);\n });\n },\n stopRecording() {\n if (!this.isRecording || !this.mediaRecorder) {\n return;\n }\n\n this.mediaRecorder.stop();\n this.isRecording = false;\n this.updateMicButton();\n },\n toggleRecording() {\n if (this.isRecording) {\n this.stopRecording();\n } else {\n this.startRecording();\n }\n },\n updateMicButton() {\n if (!this.micButton) {\n return;\n }\n\n if (this.isRecording) {\n this.micButton.classList.add('stt-recording');\n this.micButton.innerHTML = '';\n } else {\n this.micButton.classList.remove('stt-recording');\n this.micButton.innerHTML = '';\n }\n },\n streamMessage(profileId, trimmedPrompt, sessionProfileId) {\n\n if (this.stream) {\n this.stream.dispose();\n this.stream = null;\n }\n\n this.streamingStarted();\n this.showTypingIndicator();\n this.autoScroll = true;\n\n var content = '';\n var references = {};\n var lastResponseId = null;\n\n // Get the index after showing typing indicator.\n var messageIndex = this.messages.length;\n var currentSessionId = this.getSessionId();\n\n this.stream = this.connection.stream(\"SendMessage\", profileId, trimmedPrompt, currentSessionId, sessionProfileId)\n .subscribe({\n next: (chunk) => {\n let message = this.messages[messageIndex];\n\n if (!message) {\n\n if (chunk.sessionId && !currentSessionId) {\n this.initializeSession(chunk.sessionId);\n }\n\n this.hideTypingIndicator();\n // Re-assign the index after hiding the typing indicator.\n messageIndex = this.messages.length;\n let newMessage = {\n id: chunk.messageId,\n role: \"assistant\",\n title: chunk.title,\n content: \"\",\n htmlContent: \"\",\n isStreaming: true,\n userRating: null,\n };\n\n this.messages.push(newMessage);\n\n message = newMessage;\n }\n\n if (chunk.title && (!message.title || message.title !== chunk.title)) {\n message.title = chunk.title;\n }\n\n if (chunk.references && typeof chunk.references === \"object\" && Object.keys(chunk.references).length) {\n\n for (const [key, value] of Object.entries(chunk.references)) {\n references[key] = normalizeReference(value) ?? {};\n }\n }\n\n if (chunk.content) {\n\n // When the responseId changes (e.g., after an internal tool call),\n // insert a line break to visually separate response segments.\n if (chunk.responseId && lastResponseId && chunk.responseId !== lastResponseId) {\n content += '\\n\\n';\n }\n\n if (chunk.responseId) {\n lastResponseId = chunk.responseId;\n }\n\n content += chunk.content;\n }\n\n // Update the existing message\n message.rawContent = content;\n updateMessagePresentation(message, references);\n\n this.messages[messageIndex] = message;\n\n this.$nextTick(() => {\n renderChartsInMessage(message);\n this.scrollToBottom();\n });\n },\n complete: () => {\n this.processReferences(references, messageIndex);\n this.streamingFinished();\n\n let msg = this.messages[messageIndex];\n if (msg) {\n msg.isStreaming = false;\n }\n\n if (!msg || !msg.content) {\n // No content received at all.\n this.hideTypingIndicator();\n }\n\n // Trigger text-to-speech only in conversation mode.\n if (this.isConversationMode && this.textToSpeechEnabled && msg && msg.content) {\n this.synthesizeSpeech(msg.content);\n }\n\n this.stream?.dispose();\n this.stream = null;\n },\n error: (err) => {\n this.processReferences(references, messageIndex);\n this.streamingFinished();\n\n let msg = this.messages[messageIndex];\n if (msg) {\n msg.isStreaming = false;\n }\n\n this.hideTypingIndicator();\n\n if (!this.isNavigatingAway) {\n this.addMessage(this.getServiceDownMessage());\n }\n\n this.stream?.dispose();\n this.stream = null;\n\n console.error(\"Stream error:\", err);\n }\n });\n },\n getServiceDownMessage() {\n let newMessage = {\n role: \"assistant\",\n content: \"Our service is currently unavailable. Please try again later. We apologize for the inconvenience.\",\n htmlContent: \"\",\n };\n\n return newMessage;\n },\n processReferences(references, messageIndex) {\n references = normalizeReferences(references);\n\n if (Object.keys(references).length) {\n\n let message = this.messages[messageIndex];\n message.rawContent = message.rawContent ?? message.content ?? '';\n updateMessagePresentation(message, references);\n\n this.messages[messageIndex] = message;\n\n this.$nextTick(() => {\n renderChartsInMessage(message);\n this.scrollToBottom();\n });\n }\n },\n streamingStarted() {\n var stopIcon = this.buttonElement.getAttribute('data-stop-icon');\n\n if (stopIcon) {\n this.buttonElement.replaceChildren(DOMPurify.sanitize(stopIcon, { RETURN_DOM_FRAGMENT: true }));\n }\n\n if (this.inputElement) {\n this.inputElement.setAttribute('disabled', 'disabled');\n }\n },\n streamingFinished() {\n var startIcon = this.buttonElement.getAttribute('data-start-icon');\n\n if (startIcon) {\n this.buttonElement.replaceChildren(DOMPurify.sanitize(startIcon, { RETURN_DOM_FRAGMENT: true }));\n }\n\n if (this.inputElement) {\n this.inputElement.removeAttribute('disabled');\n this.inputElement.focus();\n }\n\n // Directly manipulate the DOM to stop all streaming animations.\n if (this.chatContainer) {\n var icons = this.chatContainer.querySelectorAll('.ai-streaming-icon');\n for (var i = 0; i < icons.length; i++) {\n icons[i].classList.remove('ai-streaming-icon');\n icons[i].classList.add('ai-bot-icon');\n }\n }\n\n // Also update Vue data for consistency.\n for (var i = 0; i < this.messages.length; i++) {\n if (this.messages[i].isStreaming) {\n this.messages[i].isStreaming = false;\n }\n }\n },\n handleExternalTtsStop(e) {\n if (e?.detail?.sourceId === this.ttsInstanceId) {\n return;\n }\n\n this.stopAudio(false);\n },\n updateTtsPlaybackButtons() {\n if (!this.chatContainer) {\n return;\n }\n\n var buttons = this.chatContainer.querySelectorAll('[data-tts-message-index]');\n\n buttons.forEach(button => {\n var buttonIndex = Number(button.getAttribute('data-tts-message-index'));\n var isPlaying = buttonIndex === this.ttsPlayingMessageIndex;\n\n button.classList.toggle('tts-playing', isPlaying);\n button.setAttribute('title', isPlaying ? 'Pause audio' : 'Read aloud');\n });\n },\n updateCopyButtons() {\n if (!this.chatContainer) {\n return;\n }\n\n var buttons = this.chatContainer.querySelectorAll('[data-copy-message-index]');\n\n buttons.forEach(button => {\n var buttonIndex = Number(button.getAttribute('data-copy-message-index'));\n var isCopied = buttonIndex === this.copiedMessageIndex;\n var iconHtml = isCopied\n ? ''\n : '';\n\n button.classList.toggle('text-success', isCopied);\n button.classList.toggle('text-secondary', !isCopied);\n button.setAttribute('title', isCopied ? this.copiedTitle : this.copyTitle);\n button.replaceChildren(DOMPurify.sanitize(iconHtml, { RETURN_DOM_FRAGMENT: true }));\n });\n },\n setCopyButtonState(button, isCopied) {\n if (!button) {\n return;\n }\n\n var iconHtml = isCopied\n ? ''\n : '';\n\n button.classList.toggle('text-success', isCopied);\n button.classList.toggle('text-secondary', !isCopied);\n button.setAttribute('title', isCopied ? this.copiedTitle : this.copyTitle);\n button.replaceChildren(DOMPurify.sanitize(iconHtml, { RETURN_DOM_FRAGMENT: true }));\n },\n synthesizeSpeech(text, cacheIndex) {\n if (!this.textToSpeechEnabled || !text || !this.connection) {\n return;\n }\n\n this.audioChunks = [];\n this.isPlayingAudio = true;\n this._ttsCacheIndex = cacheIndex !== undefined ? cacheIndex : -1;\n\n this.connection.invoke(\"SynthesizeSpeech\", this.getProfileId(), this.getSessionId(), text, this.ttsVoiceName)\n .catch(err => {\n console.error(\"TTS synthesis error:\", err);\n this.isPlayingAudio = false;\n this.ttsPlayingMessageIndex = -1;\n this._ttsCacheIndex = -1;\n this.$nextTick(() => this.updateTtsPlaybackButtons());\n });\n },\n toggleMessageTts(message, index) {\n if (this.ttsPlayingMessageIndex === index) {\n this.stopAudio();\n return;\n }\n\n this.stopAudio(false);\n window.dispatchEvent(new CustomEvent('crestapps-ai-chat-stop-tts', {\n detail: { sourceId: this.ttsInstanceId }\n }));\n this.ttsPlayingMessageIndex = index;\n this.$nextTick(() => this.updateTtsPlaybackButtons());\n\n if (this.ttsAudioCache[index]) {\n this.playAudioBlob(this.ttsAudioCache[index]);\n return;\n }\n\n this.synthesizeSpeech(message.content, index);\n },\n playCollectedAudio() {\n if (this.audioChunks.length === 0) {\n if (!this.currentAudioElement && this.audioPlayQueue.length === 0) {\n this.isPlayingAudio = false;\n this.ttsPlayingMessageIndex = -1;\n this.$nextTick(() => this.updateTtsPlaybackButtons());\n }\n return;\n }\n\n const totalLength = this.audioChunks.reduce((sum, chunk) => sum + chunk.length, 0);\n const combined = new Uint8Array(totalLength);\n let offset = 0;\n for (const chunk of this.audioChunks) {\n combined.set(chunk, offset);\n offset += chunk.length;\n }\n this.audioChunks = [];\n\n const blob = new Blob([combined], { type: 'audio/mp3' });\n\n if (this._ttsCacheIndex >= 0) {\n this.ttsAudioCache[this._ttsCacheIndex] = blob;\n this._ttsCacheIndex = -1;\n }\n\n // If audio is already playing, queue this blob for sequential playback.\n if (this.currentAudioElement) {\n this.audioPlayQueue.push(blob);\n return;\n }\n\n this.playAudioBlob(blob);\n },\n playAudioBlob(blob) {\n const url = URL.createObjectURL(blob);\n const audio = new Audio(url);\n\n this.currentAudioUrl = url;\n this.currentAudioElement = audio;\n this.isPlayingAudio = true;\n\n audio.addEventListener('ended', () => {\n this.currentAudioElement = null;\n this.currentAudioUrl = null;\n URL.revokeObjectURL(url);\n this.playNextInQueue();\n });\n\n audio.addEventListener('error', () => {\n this.currentAudioElement = null;\n this.currentAudioUrl = null;\n URL.revokeObjectURL(url);\n this.playNextInQueue();\n });\n\n audio.play().catch(err => {\n console.error(\"Audio playback error:\", err);\n this.currentAudioElement = null;\n this.currentAudioUrl = null;\n URL.revokeObjectURL(url);\n this.audioPlayQueue = [];\n this.isPlayingAudio = false;\n this.ttsPlayingMessageIndex = -1;\n this.$nextTick(() => this.updateTtsPlaybackButtons());\n });\n },\n playNextInQueue() {\n if (this.audioPlayQueue.length > 0) {\n var nextBlob = this.audioPlayQueue.shift();\n this.playAudioBlob(nextBlob);\n } else {\n this.isPlayingAudio = false;\n this.ttsPlayingMessageIndex = -1;\n this.$nextTick(() => this.updateTtsPlaybackButtons());\n this.conversationModeOnAudioEnded();\n }\n },\n stopAudio() {\n if (this.currentAudioElement) {\n this.currentAudioElement.pause();\n this.currentAudioElement.currentTime = 0;\n this.currentAudioElement = null;\n }\n if (this.currentAudioUrl) {\n URL.revokeObjectURL(this.currentAudioUrl);\n this.currentAudioUrl = null;\n }\n this.audioChunks = [];\n this.audioPlayQueue = [];\n this.isPlayingAudio = false;\n this.ttsPlayingMessageIndex = -1;\n this.$nextTick(() => this.updateTtsPlaybackButtons());\n },\n toggleConversationMode() {\n if (this.isConversationMode) {\n this.stopConversationMode();\n } else {\n this.startConversationMode();\n }\n },\n startConversationMode() {\n if (!this.conversationModeEnabled || this.isConversationMode || !this.connection) {\n return;\n }\n\n this.isConversationMode = true;\n this.updateConversationButton();\n this._conversationPartialTranscript = '';\n this._conversationAssistantMessage = null;\n this._conversationPartialMessage = null;\n\n // Remove any previous conversation ended notification.\n this.removeNotification('conversation-ended');\n navigator.mediaDevices.getUserMedia({ audio: { echoCancellation: true, noiseSuppression: true, autoGainControl: true } })\n .then(stream => {\n var mimeType = MediaRecorder.isTypeSupported('audio/ogg;codecs=opus')\n ? 'audio/ogg;codecs=opus'\n : MediaRecorder.isTypeSupported('audio/webm;codecs=opus')\n ? 'audio/webm;codecs=opus'\n : 'audio/webm';\n\n this.mediaRecorder = new MediaRecorder(stream, {\n mimeType: mimeType,\n audioBitsPerSecond: 128000,\n });\n\n this._conversationSubject = new signalR.Subject();\n this._conversationStream = stream;\n\n // Create an AnalyserNode for volume-based interrupt detection.\n // During TTS playback, detect when the user speaks above\n // the threshold to stop TTS (interrupt). Audio chunks are\n // always forwarded — browser echo cancellation handles\n // speaker echo so the STT stream has no gaps.\n var AudioCtx = window.AudioContext || window.webkitAudioContext;\n if (AudioCtx) {\n this._conversationAudioCtx = new AudioCtx();\n this._conversationAnalyser = this._conversationAudioCtx.createAnalyser();\n this._conversationAnalyser.fftSize = 256;\n var micSource = this._conversationAudioCtx.createMediaStreamSource(stream);\n micSource.connect(this._conversationAnalyser);\n }\n\n var pendingChunk = Promise.resolve();\n var analyser = this._conversationAnalyser;\n var interruptVolumeThreshold = 30;\n\n this.mediaRecorder.addEventListener('dataavailable', (e) => {\n if (e.data && e.data.size > 0) {\n // During TTS playback, check mic volume to detect\n // user interruption (speaking above threshold).\n if (this.isPlayingAudio && analyser) {\n var freqData = new Uint8Array(analyser.frequencyBinCount);\n analyser.getByteFrequencyData(freqData);\n var sum = 0;\n for (var k = 0; k < freqData.length; k++) { sum += freqData[k]; }\n var avg = sum / freqData.length;\n\n if (avg >= interruptVolumeThreshold) {\n // User is speaking — interrupt TTS playback.\n this.stopAudio();\n }\n }\n\n // Always send audio to STT — browser echo cancellation\n // handles speaker echo; continuous audio avoids gaps\n // that increase recognition latency.\n pendingChunk = pendingChunk.then(async () => {\n var data = await e.data.arrayBuffer();\n var uint8Array = new Uint8Array(data);\n var binaryString = uint8Array.reduce(function (str, byte) { return str + String.fromCharCode(byte); }, '');\n var base64 = btoa(binaryString);\n try {\n this._conversationSubject.next(base64);\n } catch (err) {\n // Subject may have been completed already.\n }\n });\n }\n });\n\n this.mediaRecorder.addEventListener('stop', () => {\n stream.getTracks().forEach(track => track.stop());\n pendingChunk.then(() => {\n try {\n this._conversationSubject.complete();\n } catch (err) {\n // Already completed.\n }\n });\n });\n\n var profileId = this.getProfileId();\n var sessionId = this.getSessionId() || '';\n var language = navigator.language || document.documentElement.lang || 'en-US';\n\n this.connection.send(\"StartConversation\", profileId, sessionId, this._conversationSubject, mimeType, language);\n this.mediaRecorder.start(250);\n this.isRecording = true;\n })\n .catch(err => {\n console.error('Microphone access denied:', err);\n this.isConversationMode = false;\n this.updateConversationButton();\n });\n },\n stopConversationMode() {\n if (!this.isConversationMode) {\n return;\n }\n\n this.isConversationMode = false;\n this.updateConversationButton();\n\n // Signal the server to cancel all in-progress STT/TTS streams immediately.\n if (this.connection) {\n this.connection.invoke(\"StopConversation\").catch(function () { });\n }\n\n if (this.isRecording && this.mediaRecorder) {\n this.mediaRecorder.stop();\n this.isRecording = false;\n }\n\n this.stopAudio();\n this._conversationPartialTranscript = '';\n this._conversationPartialMessage = null;\n\n // Clean up the AudioContext used for volume monitoring.\n if (this._conversationAudioCtx) {\n this._conversationAudioCtx.close().catch(function () { });\n this._conversationAudioCtx = null;\n this._conversationAnalyser = null;\n }\n\n // Mark any in-flight assistant message as done to stop the spinner.\n if (this._conversationAssistantMessage) {\n var msg = this.messages[this._conversationAssistantMessage.index];\n if (msg) {\n msg.isStreaming = false;\n }\n this._conversationAssistantMessage = null;\n }\n\n // Safety net: clear all lingering streaming indicators.\n for (var i = 0; i < this.messages.length; i++) {\n if (this.messages[i].isStreaming) {\n this.messages[i].isStreaming = false;\n }\n }\n\n // Show a \"conversation ended\" notification system message.\n this.receiveNotification({\n type: 'conversation-ended',\n content: 'Conversation ended.',\n icon: 'fa-solid fa-circle-check',\n dismissible: true,\n autoDismissMs: 5000\n });\n },\n updateConversationButton() {\n if (!this.conversationButton) {\n return;\n }\n\n if (this.isConversationMode) {\n this.conversationButton.classList.add('active', 'btn-primary');\n this.conversationButton.classList.remove('btn-dark', 'btn-outline-dark', 'btn-outline-secondary');\n this.conversationButton.title = this.conversationButton.getAttribute('data-end-title') || 'End Conversation';\n var endHtml = this.conversationButton.getAttribute('data-end-html');\n if (endHtml) {\n this.conversationButton.replaceChildren(DOMPurify.sanitize(endHtml, { RETURN_DOM_FRAGMENT: true }));\n }\n } else {\n this.conversationButton.classList.remove('active', 'btn-primary');\n this.conversationButton.classList.remove('btn-dark', 'btn-outline-secondary');\n this.conversationButton.classList.add('btn-outline-dark');\n this.conversationButton.blur();\n this.conversationButton.title = this.conversationButton.getAttribute('data-start-title') || 'Start Conversation';\n var startHtml = this.conversationButton.getAttribute('data-start-html');\n if (startHtml) {\n this.conversationButton.replaceChildren(DOMPurify.sanitize(startHtml, { RETURN_DOM_FRAGMENT: true }));\n }\n }\n },\n conversationModeSendPrompt() {\n // Legacy: only used by AudioInput mode's ReceiveTranscript.\n },\n conversationModeOnAudioEnded() {\n // Legacy: in conversation mode, audio playback continuation\n // is handled by the persistent stream. This method is only\n // called from playCollectedAudio for non-conversation TTS.\n },\n generatePrompt(element) {\n if (!element) {\n console.error('The element paramter is required.');\n\n return;\n }\n\n let templateProfileId = element.getAttribute('data-profile-id');\n let sessionId = this.getSessionId();\n let sessionProfileId = this.getProfileId();\n\n if (!templateProfileId || !sessionId) {\n\n console.error('The given element is missing data-profile-id or the session has not yet started.');\n return;\n }\n\n // streamMessage() already shows the typing indicator.\n this.streamMessage(templateProfileId, null, sessionProfileId);\n },\n createSessionUrl(baseUrl, param, value) {\n\n const fullUrl = baseUrl.toLowerCase().startsWith('http') ? baseUrl : window.location.origin + baseUrl;\n const url = new URL(fullUrl);\n\n url.searchParams.set(param, value);\n\n return url.toString();\n },\n showTypingIndicator() {\n this.addMessage({\n role: 'indicator',\n htmlContent: config.indicatorTemplate\n });\n },\n hideTypingIndicator() {\n const originalLength = this.messages.length;\n this.messages = this.messages.filter(msg => msg.role !== 'indicator');\n const removedCount = originalLength - this.messages.length;\n return removedCount;\n },\n receiveNotification(notification) {\n if (!notification || !notification.type) {\n return;\n }\n this.clearNotificationDismiss(notification.type);\n var existingIndex = this.notifications.findIndex(n => n.type === notification.type);\n if (existingIndex >= 0) {\n this.notifications.splice(existingIndex, 1, notification);\n } else {\n this.notifications.push(notification);\n }\n this.scheduleNotificationDismiss(notification);\n this.$nextTick(() => {\n this.scrollToBottom();\n });\n },\n updateNotification(notification) {\n if (!notification || !notification.type) {\n return;\n }\n this.clearNotificationDismiss(notification.type);\n var existingIndex = this.notifications.findIndex(n => n.type === notification.type);\n if (existingIndex >= 0) {\n this.notifications.splice(existingIndex, 1, notification);\n this.scheduleNotificationDismiss(notification);\n }\n },\n scheduleNotificationDismiss(notification) {\n if (!notification || !notification.type || !notification.autoDismissMs || notification.autoDismissMs <= 0) {\n return;\n }\n this.notificationDismissTimers[notification.type] = setTimeout(() => {\n this.removeNotification(notification.type);\n }, notification.autoDismissMs);\n },\n clearNotificationDismiss(notificationType) {\n var timerId = this.notificationDismissTimers[notificationType];\n if (!timerId) {\n return;\n }\n clearTimeout(timerId);\n delete this.notificationDismissTimers[notificationType];\n },\n removeNotification(notificationType) {\n this.clearNotificationDismiss(notificationType);\n this.notifications = this.notifications.filter(n => n.type !== notificationType);\n },\n dismissNotification(notificationType) {\n this.removeNotification(notificationType);\n },\n handleNotificationAction(notificationType, actionName) {\n if (!this.connection) {\n return;\n }\n var sessionId = this.getSessionId();\n this.connection.invoke(\"HandleNotificationAction\", sessionId, notificationType, actionName).catch(function (err) {\n console.error(\"Error handling notification action:\", err);\n });\n },\n scrollToBottom() {\n if (!this.autoScroll) {\n return;\n }\n setTimeout(() => {\n this.chatContainer.scrollTop = this.chatContainer.scrollHeight - this.chatContainer.clientHeight;\n }, 50);\n },\n handleUserInput(event) {\n this.prompt = event.target.value;\n },\n getProfileId() {\n return this.inputElement\n ? this.inputElement.getAttribute('data-profile-id')\n : null;\n },\n setSessionId(sessionId) {\n if (!this.inputElement) {\n return;\n }\n\n this.inputElement.setAttribute('data-session-id', sessionId || '');\n },\n resetSession() {\n this.stopRecording();\n this.rejectPendingSessionRequest('Session was reset.');\n this.setSessionId('');\n this.isSessionStarted = false;\n this.sessionRating = null;\n this.messages = [];\n this.documents = [];\n this.showPlaceholder();\n\n if (widgetBehavior && typeof widgetBehavior.onSessionReset === 'function') {\n widgetBehavior.onSessionReset(this, config);\n }\n },\n startNewSession() {\n if (!this.applyOrchestratorAvailability()) {\n return;\n }\n\n const profileId = this.getProfileId();\n if (!profileId || !this.connection) {\n return;\n }\n\n this.requestNewSession(profileId).catch(err => console.error(err));\n },\n async ensureSessionForDocuments(profileId) {\n var sessionId = this.getSessionId();\n if (sessionId) {\n return sessionId;\n }\n\n if (!profileId || !this.connection) {\n return null;\n }\n\n return await this.requestNewSession(profileId);\n },\n requestNewSession(profileId) {\n if (this.pendingSessionPromise) {\n return this.pendingSessionPromise;\n }\n\n if (!profileId || !this.connection) {\n return Promise.resolve(null);\n }\n\n this.pendingSessionPromise = new Promise((resolve, reject) => {\n this.pendingSessionResolver = resolve;\n this.pendingSessionRejector = reject;\n this.pendingSessionTimeoutId = window.setTimeout(() => {\n this.rejectPendingSessionRequest('Timed out while creating a chat session.');\n }, 15000);\n });\n\n this.connection.invoke(\"StartSession\", profileId, null).catch(err => {\n this.rejectPendingSessionRequest(err);\n });\n\n return this.pendingSessionPromise;\n },\n resolvePendingSessionRequest(sessionId) {\n if (this.pendingSessionResolver) {\n this.pendingSessionResolver(sessionId);\n }\n\n this.clearPendingSessionRequest();\n },\n rejectPendingSessionRequest(error) {\n if (this.pendingSessionRejector) {\n this.pendingSessionRejector(error);\n }\n\n this.clearPendingSessionRequest();\n },\n clearPendingSessionRequest() {\n if (this.pendingSessionTimeoutId) {\n window.clearTimeout(this.pendingSessionTimeoutId);\n }\n\n this.pendingSessionPromise = null;\n this.pendingSessionResolver = null;\n this.pendingSessionRejector = null;\n this.pendingSessionTimeoutId = null;\n },\n initializeApp() {\n this.inputElement = document.querySelector(config.inputElementSelector);\n this.buttonElement = document.querySelector(config.sendButtonElementSelector);\n this.chatContainer = document.querySelector(config.chatContainerElementSelector);\n this.placeholder = document.querySelector(config.placeholderElementSelector);\n\n if (!this.inputElement || !this.buttonElement || !this.chatContainer || !this.placeholder) {\n console.error('AI chat app could not initialize because one or more required elements were not found.', {\n inputElementSelector: config.inputElementSelector,\n sendButtonElementSelector: config.sendButtonElementSelector,\n chatContainerElementSelector: config.chatContainerElementSelector,\n placeholderElementSelector: config.placeholderElementSelector\n });\n\n return false;\n }\n\n this.applyOrchestratorAvailability();\n\n const sessionId = this.getSessionId();\n if (!hasWidgetConfig && sessionId) {\n this.loadSession(sessionId);\n }\n\n // Initialize document bar if enabled.\n if (config.sessionDocumentsEnabled && config.documentBarSelector) {\n this.documentBar = document.querySelector(config.documentBarSelector);\n if (this.documentBar) {\n this.renderDocumentBar();\n\n // Create hidden file input for document uploads.\n var fileInput = document.createElement('input');\n fileInput.type = 'file';\n fileInput.id = 'ai-chat-doc-input';\n fileInput.className = 'd-none';\n fileInput.multiple = true;\n if (config.allowedExtensions) {\n fileInput.accept = config.allowedExtensions;\n }\n fileInput.addEventListener('change', (e) => this.handleFileInputChange(e));\n this.documentBar.parentElement.appendChild(fileInput);\n\n // Set up drag-and-drop on the input area.\n var inputArea = this.inputElement ? this.inputElement.closest('.ai-admin-widget-input, .text-bg-light') : null;\n if (inputArea) {\n inputArea.addEventListener('dragover', (e) => this.handleDragOver(e));\n inputArea.addEventListener('dragleave', (e) => this.handleDragLeave(e));\n inputArea.addEventListener('drop', (e) => this.handleDrop(e));\n }\n }\n }\n\n // Pause auto-scroll when the user manually scrolls up during streaming.\n this.chatContainer.addEventListener('scroll', () => {\n if (!this.stream) {\n return;\n }\n const threshold = 30;\n const atBottom = this.chatContainer.scrollHeight - this.chatContainer.clientHeight - this.chatContainer.scrollTop <= threshold;\n this.autoScroll = atBottom;\n });\n\n this.inputElement.addEventListener('keydown', event => {\n\n if (this.stream != null) {\n return;\n }\n\n if (event.key === \"Enter\" && !event.shiftKey) {\n event.preventDefault();\n this.buttonElement.click();\n }\n });\n\n this.inputElement.addEventListener('input', (e) => {\n this.handleUserInput(e);\n\n if (e.target.value.trim()) {\n this.buttonElement.removeAttribute('disabled');\n } else {\n this.buttonElement.setAttribute('disabled', true);\n }\n });\n\n this.buttonElement.addEventListener('click', () => {\n\n if (this.stream != null) {\n this.stream.dispose();\n this.stream = null;\n\n this.streamingFinished();\n this.hideTypingIndicator();\n\n // Clean up: remove empty assistant message or stop streaming animation.\n if (this.messages.length > 0) {\n const lastMsg = this.messages[this.messages.length - 1];\n if (lastMsg.role === 'assistant' && !lastMsg.content) {\n this.messages.pop();\n } else if (lastMsg.isStreaming) {\n lastMsg.isStreaming = false;\n }\n }\n\n return;\n }\n\n this.sendMessage();\n });\n\n const promptGenerators = document.getElementsByClassName('profile-generated-prompt');\n\n for (var i = 0; i < promptGenerators.length; i++) {\n promptGenerators[i].addEventListener('click', (e) => {\n e.preventDefault();\n this.generatePrompt(e.target);\n });\n }\n\n const chatSessions = document.getElementsByClassName('chat-session-history-item');\n\n for (var i = 0; i < chatSessions.length; i++) {\n chatSessions[i].addEventListener('click', (e) => {\n e.preventDefault();\n\n var sessionId = e.target.getAttribute('data-session-id');\n\n if (!sessionId) {\n console.error('an element with the class chat-session-history-item with no data-session-id set.');\n\n return;\n }\n\n this.loadSession(sessionId);\n this.showChatScreen();\n });\n }\n\n const initialMessages = Array.isArray(config.messages) ? config.messages : [];\n\n for (let i = 0; i < initialMessages.length; i++) {\n this.addMessage(initialMessages[i]);\n }\n\n // Update feedback icons in the DOM after initial messages have rendered.\n this.$nextTick(() => {\n this.refreshAllFeedbackIcons();\n });\n\n // Delegate click for code block copy buttons.\n if (this.chatContainer) {\n this.chatContainer.addEventListener('click', (e) => {\n var btn = e.target.closest('.ai-code-copy-btn');\n if (!btn) {\n return;\n }\n\n var block = btn.closest('.ai-code-block') || btn.closest('pre');\n if (!block) {\n return;\n }\n\n var codeEl = block.querySelector('code');\n if (codeEl) {\n navigator.clipboard.writeText(codeEl.textContent);\n var copiedText = config.codeCopiedText || 'Copied!';\n btn.innerHTML = ' ' + copiedText;\n setTimeout(() => {\n btn.innerHTML = '';\n }, 2000);\n }\n });\n }\n\n // Initialize speech-to-text microphone button.\n if (this.speechToTextEnabled && config.micButtonElementSelector) {\n this.micButton = document.querySelector(config.micButtonElementSelector);\n if (this.micButton) {\n this.micButton.style.display = '';\n this.micButton.addEventListener('click', () => {\n this.toggleRecording();\n });\n }\n }\n\n // Initialize conversation mode button.\n if (this.conversationModeEnabled && config.conversationButtonElementSelector) {\n this.conversationButton = document.querySelector(config.conversationButtonElementSelector);\n if (this.conversationButton) {\n this.conversationButton.addEventListener('click', () => {\n this.toggleConversationMode();\n });\n }\n }\n\n return true;\n },\n loadSession(sessionId) {\n this.connection.invoke(\"LoadSession\", sessionId).catch(err => console.error(err));\n },\n reloadCurrentSession() {\n\n var sessionId = this.getSessionId();\n if (sessionId) {\n this.loadSession(sessionId);\n }\n },\n initializeSession(sessionId, force) {\n if (this.isSessionStarted && !force) {\n if (sessionId && this.getSessionId() === sessionId) {\n this.resolvePendingSessionRequest(sessionId);\n }\n\n return\n }\n this.fireEvent(new CustomEvent(\"initializingSessionCoreAIChat\", { detail: { sessionId: sessionId } }))\n this.setSessionId(sessionId);\n this.isSessionStarted = true;\n this.resolvePendingSessionRequest(sessionId);\n\n if (widgetBehavior && typeof widgetBehavior.onSessionInitialized === 'function') {\n widgetBehavior.onSessionInitialized(this, sessionId, config);\n }\n },\n getSessionId() {\n let sessionId = this.inputElement\n ? this.inputElement.getAttribute('data-session-id')\n : null;\n\n if (!sessionId && widgetBehavior && typeof widgetBehavior.resolveSessionId === 'function') {\n sessionId = widgetBehavior.resolveSessionId(this, config);\n }\n\n return sessionId;\n },\n clearCopiedMessageState() {\n if (this.copyResetTimeoutId) {\n window.clearTimeout(this.copyResetTimeoutId);\n this.copyResetTimeoutId = null;\n }\n\n if (this.activeCopyButton) {\n this.setCopyButtonState(this.activeCopyButton, false);\n this.activeCopyButton = null;\n }\n\n this.copiedMessageIndex = -1;\n },\n copyResponse(message, index, event) {\n const text = message && typeof message === 'object'\n ? message.copyContent ?? message.content ?? ''\n : message ?? '';\n const button = event?.currentTarget || event?.target?.closest?.('[data-copy-message-index]') || null;\n\n navigator.clipboard.writeText(text)\n .then(() => {\n this.clearCopiedMessageState();\n this.copiedMessageIndex = typeof index === 'number' ? index : -1;\n this.activeCopyButton = button;\n\n if (button) {\n this.setCopyButtonState(button, true);\n } else {\n this.$nextTick(() => this.updateCopyButtons());\n }\n\n this.copyResetTimeoutId = window.setTimeout(() => {\n this.clearCopiedMessageState();\n this.$nextTick(() => this.updateCopyButtons());\n }, Number(config.copyResetDelayMs) || 2000);\n })\n .catch(err => console.error('Failed to copy response:', err));\n },\n updateFeedbackIcons(container, userRating) {\n if (!container) {\n return;\n }\n\n var upBtn = container.querySelector('.rate-up-btn');\n var downBtn = container.querySelector('.rate-down-btn');\n\n // Keep feedback icons as simple span-based Font Awesome markup so\n // later state updates do not depend on i2svg replacement.\n if (upBtn) {\n var upClass = userRating === true ? 'fa-solid fa-thumbs-up' : 'fa-regular fa-thumbs-up';\n var upIcon = document.createElement('span');\n upIcon.className = upClass;\n upIcon.style.fontSize = '0.9rem';\n upBtn.textContent = '';\n upBtn.appendChild(upIcon);\n }\n\n if (downBtn) {\n var downClass = userRating === false ? 'fa-solid fa-thumbs-down' : 'fa-regular fa-thumbs-down';\n var downIcon = document.createElement('span');\n downIcon.className = downClass;\n downIcon.style.fontSize = '0.9rem';\n downBtn.textContent = '';\n downBtn.appendChild(downIcon);\n }\n },\n refreshAllFeedbackIcons() {\n var containers = this.$el.querySelectorAll('.ai-chat-message-assistant-feedback');\n\n for (var i = 0; i < containers.length; i++) {\n var msgId = containers[i].getAttribute('data-message-id');\n var msg = this.messages.find(m => m.id === msgId);\n\n if (msg) {\n this.updateFeedbackIcons(containers[i], msg.userRating);\n }\n }\n },\n rateMessage(message, isPositive, event) {\n var sessionId = this.getSessionId();\n\n if (!sessionId || !message.id || !this.connection) {\n return;\n }\n\n // Toggle: clicking the same rating again clears it.\n var newRating = message.userRating === isPositive ? null : isPositive;\n message.userRating = newRating;\n\n // Find the feedback container by message ID for reliable DOM targeting.\n var feedbackContainer = this.$el.querySelector(\n '.ai-chat-message-assistant-feedback[data-message-id=\"' + message.id + '\"]'\n );\n\n this.updateFeedbackIcons(feedbackContainer, newRating);\n\n // Trigger spark animation after Font Awesome has re-processed icons.\n if (newRating !== null && feedbackContainer) {\n setTimeout(() => {\n var btnClass = isPositive ? '.rate-up-btn' : '.rate-down-btn';\n var btn = feedbackContainer.querySelector(btnClass);\n\n if (btn) {\n btn.classList.remove('spark-effect');\n void btn.offsetWidth;\n btn.classList.add('spark-effect');\n btn.addEventListener('animationend', function onEnd() {\n btn.removeEventListener('animationend', onEnd);\n btn.classList.remove('spark-effect');\n });\n }\n }, 50);\n }\n\n this.connection.invoke(\"RateMessage\", sessionId, message.id, isPositive).catch(function (err) {\n console.error('Failed to rate message:', err);\n });\n }\n },\n watch: {\n documents: {\n handler() {\n this.renderDocumentBar();\n if (widgetBehavior && typeof widgetBehavior.onDocumentsChanged === 'function') {\n widgetBehavior.onDocumentsChanged(this, this.documents, config);\n }\n },\n deep: true\n },\n isUploading() { this.renderDocumentBar(); },\n isDocumentOperationPending() { this.renderDocumentBar(); },\n isPlayingAudio() {\n // Reserved for future use — volume-based interrupt detection\n // no longer mutes tracks; browser echo cancellation handles echo.\n },\n copiedMessageIndex() {\n this.$nextTick(() => this.updateCopyButtons());\n },\n isConversationMode(active) {\n // Hide/show mic button.\n if (this.micButton) {\n this.micButton.style.display = active ? 'none' : (this.speechToTextEnabled ? '' : 'none');\n }\n\n // Hide/show send button.\n if (this.buttonElement) {\n this.buttonElement.style.display = active ? 'none' : '';\n }\n\n // Disable/enable textarea.\n if (this.inputElement) {\n this.inputElement.disabled = active;\n if (active) {\n this.inputElement.placeholder = '';\n }\n }\n }\n },\n mounted() {\n (async () => {\n await this.startConnection();\n const isInitialized = this.initializeApp();\n if (isInitialized && hasWidgetConfig && widgetBehavior && typeof widgetBehavior.onMounted === 'function') {\n widgetBehavior.onMounted(this, config);\n }\n\n this.$nextTick(() => {\n this.updateCopyButtons();\n refreshFontAwesomeIcons(this.$el);\n this.fontAwesomeObserver = observeFontAwesomeIcons(this.$el);\n });\n })();\n\n window.addEventListener('beforeunload', this.handleBeforeUnload);\n window.addEventListener('crestapps-ai-chat-stop-tts', this.handleExternalTtsStop);\n },\n beforeUnmount() {\n window.removeEventListener('beforeunload', this.handleBeforeUnload);\n window.removeEventListener('crestapps-ai-chat-stop-tts', this.handleExternalTtsStop);\n\n if (this.fontAwesomeObserver) {\n this.fontAwesomeObserver.disconnect();\n this.fontAwesomeObserver = null;\n }\n\n this.clearCopiedMessageState();\n this.stopAudio(false);\n\n if (this.stream) {\n this.stream.dispose();\n this.stream = null;\n }\n if (this.connection) {\n this.connection.stop();\n }\n\n if (widgetBehavior && typeof widgetBehavior.onBeforeUnmount === 'function') {\n widgetBehavior.onBeforeUnmount(this, config);\n }\n },\n template: config.messageTemplate\n };\n\n const app = Vue.createApp(appDefinition).mount(config.appElementSelector);\n\n if (widgetBehavior && typeof widgetBehavior.attach === 'function') {\n widgetBehavior.attach(app, config);\n }\n\n return app;\n };\n\n const autoInitializeSelector = '[data-coreai-chat-config],[data-coreai-chat-app-element-selector]';\n\n function getAttributeValue(element, attributeName) {\n const value = element.getAttribute(attributeName);\n return value === null || value === '' ? null : value;\n }\n\n function parseBooleanAttributeValue(value) {\n if (value === null || value === undefined) {\n return null;\n }\n\n if (typeof value === 'boolean') {\n return value;\n }\n\n const normalized = String(value).trim().toLowerCase();\n if (normalized === 'true') {\n return true;\n }\n\n if (normalized === 'false') {\n return false;\n }\n\n return null;\n }\n\n function parseJsonAttribute(element, attributeName, description) {\n const rawValue = getAttributeValue(element, attributeName);\n if (!rawValue) {\n return null;\n }\n\n try {\n return JSON.parse(rawValue);\n } catch (error) {\n console.error('Failed to parse ' + description + ' JSON.', error);\n return null;\n }\n }\n\n function buildConfigFromDataAttributes(element, options) {\n const settings = options || {};\n\n if (element.hasAttribute('data-coreai-chat-widget-container-selector') && settings.allowWidgetHost !== true) {\n return null;\n }\n\n const appElementSelector = getAttributeValue(element, 'data-coreai-chat-app-element-selector');\n if (!appElementSelector) {\n return null;\n }\n\n const config = {\n signalRHubUrl: getAttributeValue(element, 'data-coreai-chat-signalr-hub-url'),\n appElementSelector: appElementSelector,\n chatContainerElementSelector: getAttributeValue(element, 'data-coreai-chat-container-element-selector'),\n inputElementSelector: getAttributeValue(element, 'data-coreai-chat-input-element-selector'),\n sendButtonElementSelector: getAttributeValue(element, 'data-coreai-chat-send-button-element-selector'),\n placeholderElementSelector: getAttributeValue(element, 'data-coreai-chat-placeholder-element-selector'),\n messages: parseJsonAttribute(element, 'data-coreai-chat-messages', 'CoreAI chat messages') ?? undefined,\n chatMode: getAttributeValue(element, 'data-coreai-chat-mode'),\n micButtonElementSelector: getAttributeValue(element, 'data-coreai-chat-mic-button-element-selector'),\n conversationButtonElementSelector: getAttributeValue(element, 'data-coreai-chat-conversation-button-element-selector'),\n ttsVoiceName: getAttributeValue(element, 'data-coreai-chat-tts-voice-name'),\n documentBarSelector: getAttributeValue(element, 'data-coreai-chat-document-bar-selector'),\n uploadDocumentUrl: getAttributeValue(element, 'data-coreai-chat-upload-document-url'),\n removeDocumentUrl: getAttributeValue(element, 'data-coreai-chat-remove-document-url'),\n allowedExtensions: getAttributeValue(element, 'data-coreai-chat-allowed-extensions'),\n supportedExtensionsText: getAttributeValue(element, 'data-coreai-chat-supported-extensions-text'),\n existingDocuments: parseJsonAttribute(element, 'data-coreai-chat-existing-documents', 'CoreAI chat existing documents') ?? undefined,\n initialPrompt: getAttributeValue(element, 'data-coreai-chat-initial-prompt'),\n userLabel: getAttributeValue(element, 'data-coreai-chat-user-label'),\n assistantLabel: getAttributeValue(element, 'data-coreai-chat-assistant-label'),\n copyTitle: getAttributeValue(element, 'data-coreai-chat-copy-title'),\n copiedTitle: getAttributeValue(element, 'data-coreai-chat-copied-title'),\n };\n\n const booleanAttributes = {\n metricsEnabled: 'data-coreai-chat-metrics-enabled',\n textToSpeechEnabled: 'data-coreai-chat-text-to-speech-enabled',\n sessionDocumentsEnabled: 'data-coreai-chat-session-documents-enabled',\n singleResponseMode: 'data-coreai-chat-single-response-mode',\n };\n\n Object.keys(booleanAttributes).forEach(key => {\n const parsed = parseBooleanAttributeValue(getAttributeValue(element, booleanAttributes[key]));\n if (parsed !== null) {\n config[key] = parsed;\n }\n });\n\n return compactObject(config);\n }\n\n function buildConfigFromElement(element, options) {\n const jsonConfig = parseJsonAttribute(element, 'data-coreai-chat-config', 'CoreAI chat config');\n const attributeConfig = buildConfigFromDataAttributes(element, options);\n\n if (!jsonConfig && !attributeConfig) {\n return null;\n }\n\n return Object.assign({}, jsonConfig || {}, attributeConfig || {});\n }\n\n function initializeFromElement(element) {\n if (!element || element.dataset.coreAiChatInitialized === 'true') {\n return element ? element.__coreAIChatApp || null : null;\n }\n\n const config = buildConfigFromElement(element);\n if (!config) {\n return null;\n }\n\n const app = initialize(config);\n if (!app) {\n return null;\n }\n\n element.dataset.coreAiChatInitialized = 'true';\n element.__coreAIChatApp = app;\n\n return app;\n }\n\n function scanForAutoInitialization(root) {\n if (!root || typeof root.querySelectorAll !== 'function') {\n return;\n }\n\n if (typeof root.matches === 'function' && root.matches(autoInitializeSelector)) {\n initializeFromElement(root);\n }\n\n root.querySelectorAll(autoInitializeSelector).forEach(initializeFromElement);\n }\n\n function startAutoInitialization() {\n scanForAutoInitialization(document);\n\n if (typeof MutationObserver === 'undefined') {\n return;\n }\n\n const observer = new MutationObserver(mutations => {\n mutations.forEach(mutation => {\n mutation.addedNodes.forEach(node => {\n if (node && node.nodeType === 1) {\n scanForAutoInitialization(node);\n }\n });\n });\n });\n\n observer.observe(document.body, {\n childList: true,\n subtree: true,\n });\n }\n\n if (document.readyState === 'loading') {\n document.addEventListener('DOMContentLoaded', startAutoInitialization, { once: true });\n } else {\n startAutoInitialization();\n }\n\n return {\n initialize: initialize,\n initializeFromElement: initializeFromElement,\n buildConfigFromElement: buildConfigFromElement,\n };\n}();\n\n// Download chart as image via event delegation (DOMPurify strips inline onclick).\ndocument.addEventListener('click', function (e) {\n const btn = e.target.closest('.download-chart-btn');\n if (!btn) {\n return;\n }\n const chartId = btn.getAttribute('data-chart-id');\n const canvas = chartId ? document.getElementById(chartId) : null;\n if (!canvas) {\n console.error('Chart canvas not found:', chartId);\n return;\n }\n const link = document.createElement('a');\n link.download = 'chart-' + chartId + '.png';\n link.href = canvas.toDataURL('image/png');\n link.click();\n});\n\n// Intercept download clicks for data-URI images and convert to blob downloads.\ndocument.addEventListener('click', function (e) {\n const link = e.target.closest('.ai-download-image');\n if (!link) {\n return;\n }\n\n const container = link.closest('.generated-image-container');\n const img = container?.querySelector('img');\n if (!img) {\n return;\n }\n\n const src = img.src;\n if (!src || !src.startsWith('data:')) {\n return; // Normal URL – let the default behaviour handle it.\n }\n\n e.preventDefault();\n\n fetch(src)\n .then(function (res) { return res.blob(); })\n .then(function (blob) {\n const url = URL.createObjectURL(blob);\n const a = document.createElement('a');\n a.href = url;\n a.download = link.getAttribute('download') || 'generated-image.png';\n document.body.appendChild(a);\n a.click();\n document.body.removeChild(a);\n setTimeout(function () { URL.revokeObjectURL(url); }, 100);\n })\n .catch(function (err) { console.error('Failed to download image:', err); });\n});\n"]} diff --git a/src/Resources/CrestApps.AI.Resources/wwwroot/scripts/ai-chat.min.js b/src/Resources/CrestApps.AI.Resources/wwwroot/scripts/ai-chat.min.js index ee89ad46..7553ce84 100644 --- a/src/Resources/CrestApps.AI.Resources/wwwroot/scripts/ai-chat.min.js +++ b/src/Resources/CrestApps.AI.Resources/wwwroot/scripts/ai-chat.min.js @@ -1,2 +1,2 @@ -var _excluded=["placeholder"];function _regenerator(){/*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/babel/babel/blob/main/packages/babel-helpers/LICENSE */var e,t,n="function"==typeof Symbol?Symbol:{},i=n.iterator||"@@iterator",o=n.toStringTag||"@@toStringTag";function s(n,i,o,s){var c=i&&i.prototype instanceof r?i:r,l=Object.create(c.prototype);return _regeneratorDefine2(l,"_invoke",function(n,i,o){var s,r,c,l=0,u=o||[],d=!1,h={p:0,n:0,v:e,a:f,f:f.bind(e,4),d:function(t,n){return s=t,r=0,c=e,h.n=n,a}};function f(n,i){for(r=n,c=i,t=0;!d&&l&&!o&&t3?(o=p===i)&&(c=s[(r=s[4])?5:(r=3,3)],s[4]=s[5]=e):s[0]<=f&&((o=n<2&&fi||i>p)&&(s[4]=n,s[5]=i,h.n=p,r=0))}if(o||n>1)return a;throw d=!0,i}return function(o,u,p){if(l>1)throw TypeError("Generator is already running");for(d&&1===u&&f(u,p),r=u,c=p;(t=r<2?e:c)||!d;){s||(r?r<3?(r>1&&(h.n=-1),f(r,c)):h.n=c:h.v=c);try{if(l=2,s){if(r||(o="next"),t=s[o]){if(!(t=t.call(s,c)))throw TypeError("iterator result is not an object");if(!t.done)return t;c=t.value,r<2&&(r=0)}else 1===r&&(t=s.return)&&t.call(s),r<2&&(c=TypeError("The iterator does not provide a '"+o+"' method"),r=1);s=e}else if((t=(d=h.n<0)?c:n.call(i,h))!==a)break}catch(t){s=e,r=1,c=t}finally{l=1}}return{value:t,done:d}}}(n,o,s),!0),l}var a={};function r(){}function c(){}function l(){}t=Object.getPrototypeOf;var u=[][i]?t(t([][i]())):(_regeneratorDefine2(t={},i,function(){return this}),t),d=l.prototype=r.prototype=Object.create(u);function h(e){return Object.setPrototypeOf?Object.setPrototypeOf(e,l):(e.__proto__=l,_regeneratorDefine2(e,o,"GeneratorFunction")),e.prototype=Object.create(d),e}return c.prototype=l,_regeneratorDefine2(d,"constructor",l),_regeneratorDefine2(l,"constructor",c),c.displayName="GeneratorFunction",_regeneratorDefine2(l,o,"GeneratorFunction"),_regeneratorDefine2(d),_regeneratorDefine2(d,o,"Generator"),_regeneratorDefine2(d,i,function(){return this}),_regeneratorDefine2(d,"toString",function(){return"[object Generator]"}),(_regenerator=function(){return{w:s,m:h}})()}function _regeneratorDefine2(e,t,n,i){var o=Object.defineProperty;try{o({},"",{})}catch(e){o=0}_regeneratorDefine2=function(e,t,n,i){function s(t,n){_regeneratorDefine2(e,t,function(e){return this._invoke(t,n,e)})}t?o?o(e,t,{value:n,enumerable:!i,configurable:!i,writable:!i}):e[t]=n:(s("next",0),s("throw",1),s("return",2))},_regeneratorDefine2(e,t,n,i)}function asyncGeneratorStep(e,t,n,i,o,s,a){try{var r=e[s](a),c=r.value}catch(e){return void n(e)}r.done?t(c):Promise.resolve(c).then(i,o)}function _asyncToGenerator(e){return function(){var t=this,n=arguments;return new Promise(function(i,o){var s=e.apply(t,n);function a(e){asyncGeneratorStep(s,i,o,a,r,"next",e)}function r(e){asyncGeneratorStep(s,i,o,a,r,"throw",e)}a(void 0)})}}function _toConsumableArray(e){return _arrayWithoutHoles(e)||_iterableToArray(e)||_unsupportedIterableToArray(e)||_nonIterableSpread()}function _nonIterableSpread(){throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}function _iterableToArray(e){if("undefined"!=typeof Symbol&&null!=e[Symbol.iterator]||null!=e["@@iterator"])return Array.from(e)}function _arrayWithoutHoles(e){if(Array.isArray(e))return _arrayLikeToArray(e)}function _objectWithoutProperties(e,t){if(null==e)return{};var n,i,o=_objectWithoutPropertiesLoose(e,t);if(Object.getOwnPropertySymbols){var s=Object.getOwnPropertySymbols(e);for(i=0;i=e.length?{done:!0}:{done:!1,value:e[i++]}},e:function(e){throw e},f:o}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var s,a=!0,r=!1;return{s:function(){n=n.call(e)},n:function(){var e=n.next();return a=e.done,e},e:function(e){r=!0,s=e},f:function(){try{a||null==n.return||n.return()}finally{if(r)throw s}}}}function _slicedToArray(e,t){return _arrayWithHoles(e)||_iterableToArrayLimit(e,t)||_unsupportedIterableToArray(e,t)||_nonIterableRest()}function _nonIterableRest(){throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}function _unsupportedIterableToArray(e,t){if(e){if("string"==typeof e)return _arrayLikeToArray(e,t);var n={}.toString.call(e).slice(8,-1);return"Object"===n&&e.constructor&&(n=e.constructor.name),"Map"===n||"Set"===n?Array.from(e):"Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)?_arrayLikeToArray(e,t):void 0}}function _arrayLikeToArray(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,i=Array(t);n\n \n
\n
\n \n {{ notification.content }}\n \n
\n
\n \n
\n
\n \n ',indicatorTemplate:'\n
\n
\n \n Assistant\n
\n
\n '};function t(e){if(!e)return"";var t=e.trim();return/^javascript:/i.test(t)||/^vbscript:/i.test(t)||/^data:text\/html/i.test(t)?"":e}function n(e){var t=document.createElement("span");return t.textContent=e,t.innerHTML}function i(e){var t=window.FontAwesome;(function(e){if(!e||1!==e.nodeType)return!1;var t='i[class*="fa-"],i.fa,i.fas,i.far,i.fab';return!("function"!=typeof e.matches||!e.matches(t))||"function"==typeof e.querySelector&&!!e.querySelector(t)})(e)&&t&&t.dom&&"function"==typeof t.dom.i2svg&&t.dom.i2svg({node:e})}function o(e){if(!e||"undefined"==typeof MutationObserver)return null;var t=new MutationObserver(function(e){e.forEach(function(e){e.addedNodes.forEach(function(e){i(e)})})});return t.observe(e,{childList:!0,subtree:!0}),t}function s(e){var n,i,o,s,a,r,c,l,u,d,h;if(!e||"object"!==_typeof(e))return null;var f=Object.assign({},e);return f.index=null!==(n=null!==(i=f.index)&&void 0!==i?i:f.Index)&&void 0!==n?n:0,f.text=null!==(o=null!==(s=f.text)&&void 0!==s?s:f.Text)&&void 0!==o?o:null,f.title=null!==(a=null!==(r=f.title)&&void 0!==r?r:f.Title)&&void 0!==a?a:null,f.link=t(null!==(c=null!==(l=f.link)&&void 0!==l?l:f.Link)&&void 0!==c?c:null),f.referenceType=null!==(u=null!==(d=f.referenceType)&&void 0!==d?d:f.ReferenceType)&&void 0!==u?u:null,f.isGenerated=!0===(null!==(h=f.isGenerated)&&void 0!==h?h:f.IsGenerated),f}function a(e){return!(!e||"object"!==_typeof(e))&&("string"==typeof e.referenceType&&"document"===e.referenceType.toLowerCase()||!("string"!=typeof e.link||!/\/ai\/documents\/.+\/download(?:$|\?)/i.test(e.link)))}function r(e){if(!e||"object"!==_typeof(e))return{};for(var t={},n=0,i=Object.entries(e);n".concat(S.displayIndex,"
"))}n=n.replaceAll("",",");var A,E=_createForOfIteratorHelper(l);try{for(E.s();!(A=E.n()).done;){var C=_slicedToArray(A.value,2),T=C[0],w=C[1];d.push({referenceKey:T,displayIndex:h,label:c(w,T),link:w.link||null,isDownload:!0,placeholder:null}),h++}}catch(e){E.e(e)}finally{E.f()}return{content:n,citations:d.map(function(e){return e.placeholder,_objectWithoutProperties(e,_excluded)})}}(i,n);return e.rawContent=i,e.content=i,e.displayContent=o.content,e.references=n,e.citationReferences=o.citations,e.copyContent=function(e,t){var n=(e||"").trim();if(!n||!Array.isArray(t)||0===t.length)return n;var i,o=_createForOfIteratorHelper(t);try{for(o.s();!(i=o.n()).done;){var s=i.value;n=n.replaceAll(s.referenceKey,"[".concat(s.displayIndex,"]"))}}catch(e){o.e(e)}finally{o.f()}n+="\n\nReferences:\n";var a,r=_createForOfIteratorHelper(t);try{for(r.s();!(a=r.n()).done;){var c=a.value;n+="".concat(c.displayIndex,". ").concat(c.label),c.link&&(n+=" - ".concat(c.link)),n+="\n"}}catch(e){r.e(e)}finally{r.f()}return n.trimEnd()}(i,o.citations),e.htmlContent=m(o.content,e),e}var u=new marked.Renderer;u.link=function(e){var n=t(e.href);return n?'').concat(e.text,""):e.text||""},u.code=function(e){var t=e.text||"",i=(e.lang||"").trim(),o=t;if("undefined"!=typeof hljs)if(i&&hljs.getLanguage(i))try{o=hljs.highlight(t,{language:i}).value}catch(e){}else try{o=hljs.highlightAuto(t).value}catch(e){}else o=n(t);var s=i?n(i):"code";return'
'.concat(s,'
').concat(o,"
")},u.image=function(n){var i=t(n.href);if(!i)return"";var o=n.text||e.generatedImageAltText,s=e.generatedImageMaxWidth;return'
\n ').concat(o,'\n
\n \n \n \n
\n
')};var d=0,h=[];function f(e){if(e&&e._pendingCharts&&e._pendingCharts.length){var t=_toConsumableArray(e._pendingCharts);e._pendingCharts=[],requestAnimationFrame(function(){var e,n=_createForOfIteratorHelper(t);try{for(n.s();!(e=n.n()).done;){var i=e.value;p(i.chartId,i.config)}}catch(e){n.e(e)}finally{n.f()}})}}function p(e,t){var n=document.getElementById(e);if(!n)return!1;if("undefined"==typeof Chart)return console.warn('Chart.js is not loaded. To render interactive charts, include the Chart.js library on the page (e.g., ).');\n return false;\n }\n\n // When the canvas is inside a hidden container (e.g., a widget panel with\n // display:none), it has zero dimensions and Chart.js cannot render correctly.\n // Keep the config in __chartConfigs so renderPendingCharts() can retry later\n // once the container becomes visible.\n if (canvas.offsetParent === null) {\n window.__chartConfigs[chartId] = config;\n return false;\n }\n\n try {\n if (canvas._chartInstance) {\n canvas._chartInstance.destroy();\n }\n\n const cfg = typeof config === 'string' ? JSON.parse(config) : config;\n cfg.options ??= {};\n cfg.options.responsive = true;\n cfg.options.maintainAspectRatio = true;\n cfg.options.aspectRatio ??= 4 / 3;\n\n canvas._chartInstance = new Chart(canvas, cfg);\n delete window.__chartConfigs[chartId];\n return true;\n } catch (e) {\n console.error('Error creating chart:', e);\n return false;\n }\n }\n\n // Global function: renders any chart canvases whose configs are in the\n // global __chartConfigs map. Called by pages (e.g., Chat Interactions)\n // that share the marked instance but have their own rendering pipeline.\n window.renderPendingCharts = function () {\n if (typeof Chart === 'undefined') {\n return;\n }\n\n const configs = window.__chartConfigs;\n if (!configs) {\n return;\n }\n\n requestAnimationFrame(() => {\n for (const chartId of Object.keys(configs)) {\n renderChartOnCanvas(chartId, configs[chartId]);\n }\n });\n };\n\n // Parse markdown content via marked (which natively handles [chart:...] markers\n // through the registered extension) and collect pending chart configs for later\n // Chart.js rendering.\n function parseMarkdownContent(content, message) {\n _pendingCharts = [];\n const html = marked.parse(content, { renderer });\n message._pendingCharts = _pendingCharts.length > 0 ? [..._pendingCharts] : [];\n return DOMPurify.sanitize(html, { ADD_TAGS: ['canvas'], ADD_ATTR: ['target'] });\n }\n\n function compactObject(source) {\n if (!source || typeof source !== 'object') {\n return {};\n }\n\n return Object.fromEntries(\n Object.entries(source).filter(([, value]) => value !== undefined)\n );\n }\n\n function resolveIndicatorTemplate(template, assistantLabel) {\n if (!template) {\n return template;\n }\n\n const encodedAssistantLabel = escapeHtmlEntities(assistantLabel || 'Assistant');\n return template.replace(/\\{\\{\\s*assistantLabel\\s*\\}\\}/g, encodedAssistantLabel);\n }\n\n const initialize = (instanceConfig) => {\n const normalizedInstanceConfig = compactObject(instanceConfig);\n const normalizedWidgetConfig = compactObject(normalizedInstanceConfig.widget);\n const config = Object.assign({}, defaultConfig, normalizedInstanceConfig);\n config.widget = Object.assign({}, defaultConfig.widget || {}, normalizedWidgetConfig);\n config.indicatorTemplate = resolveIndicatorTemplate(config.indicatorTemplate, config.assistantLabel);\n const hasWidgetConfig = !!(normalizedWidgetConfig.chatWidgetContainer && normalizedWidgetConfig.chatWidgetStateName);\n const widgetBehavior = window.coreAIChatWidgetBehavior || null;\n // Keep defaultConfig in sync so renderers use overridden values\n defaultConfig = config;\n\n if (!config.signalRHubUrl) {\n console.error('The signalRHubUrl is required.');\n return;\n }\n\n if (!config.appElementSelector) {\n console.error('The appElementSelector is required.');\n return;\n }\n\n if (!config.chatContainerElementSelector) {\n console.error('The chatContainerElementSelector is required.');\n return;\n }\n\n if (!config.inputElementSelector) {\n console.error('The inputElementSelector is required.');\n return;\n }\n\n if (!config.sendButtonElementSelector) {\n console.error('The sendButtonElementSelector is required.');\n return;\n }\n\n const appDefinition = {\n data() {\n return {\n inputElement: null,\n buttonElement: null,\n chatContainer: null,\n placeholder: null,\n isSessionStarted: false,\n isPlaceholderVisible: true,\n isStreaming: false,\n isNavigatingAway: false,\n autoScroll: true,\n stream: null,\n messages: [],\n notifications: [],\n prompt: '',\n documents: config.existingDocuments || [],\n isUploading: false,\n isDocumentOperationPending: false,\n documentOperationQueue: null,\n uploadErrors: [],\n isDragOver: false,\n documentBar: null,\n metricsEnabled: !!config.metricsEnabled,\n userLabel: config.userLabel,\n assistantLabel: config.assistantLabel,\n thumbsUpTitle: config.thumbsUpTitle,\n thumbsDownTitle: config.thumbsDownTitle,\n copyTitle: config.copyTitle,\n copiedTitle: config.copiedTitle,\n isRecording: false,\n mediaRecorder: null,\n preRecordingPrompt: '',\n micButton: null,\n speechToTextEnabled: config.chatMode === 'AudioInput' || config.chatMode === 'Conversation',\n textToSpeechEnabled: config.chatMode === 'Conversation' || !!config.textToSpeechEnabled,\n ttsVoiceName: config.ttsVoiceName || null,\n audioChunks: [],\n audioPlayQueue: [],\n isPlayingAudio: false,\n currentAudioElement: null,\n currentAudioUrl: null,\n ttsButton: null,\n ttsPlayingMessageIndex: -1,\n ttsAudioCache: {},\n ttsInstanceId: 'ai-chat-' + Math.random().toString(36).slice(2),\n singleResponseMode: !!config.singleResponseMode,\n conversationModeEnabled: config.chatMode === 'Conversation',\n conversationButton: null,\n isConversationMode: false,\n notificationDismissTimers: {},\n pendingSessionPromise: null,\n pendingSessionResolver: null,\n pendingSessionRejector: null,\n pendingSessionTimeoutId: null,\n copiedMessageIndex: -1,\n copyResetTimeoutId: null,\n activeCopyButton: null,\n };\n },\n computed: {\n lastAssistantIndex() {\n for (var i = this.messages.length - 1; i >= 0; i--) {\n if (this.messages[i].role === 'assistant') {\n return i;\n }\n }\n return -1;\n }\n },\n methods: {\n handleBeforeUnload() {\n this.isNavigatingAway = true;\n },\n handleDragOver(e) {\n if (!config.sessionDocumentsEnabled) return;\n e.preventDefault();\n e.stopPropagation();\n this.isDragOver = true;\n var inputArea = this.inputElement ? this.inputElement.closest('.ai-admin-widget-input, .text-bg-light') : null;\n if (inputArea) inputArea.classList.add('ai-chat-drag-over');\n },\n handleDragLeave(e) {\n if (!config.sessionDocumentsEnabled) return;\n e.preventDefault();\n e.stopPropagation();\n this.isDragOver = false;\n var inputArea = this.inputElement ? this.inputElement.closest('.ai-admin-widget-input, .text-bg-light') : null;\n if (inputArea) inputArea.classList.remove('ai-chat-drag-over');\n },\n handleDrop(e) {\n if (!config.sessionDocumentsEnabled) return;\n e.preventDefault();\n e.stopPropagation();\n this.isDragOver = false;\n var inputArea = this.inputElement ? this.inputElement.closest('.ai-admin-widget-input, .text-bg-light') : null;\n if (inputArea) inputArea.classList.remove('ai-chat-drag-over');\n if (e.dataTransfer && e.dataTransfer.files && e.dataTransfer.files.length > 0) {\n this.uploadFiles(Array.from(e.dataTransfer.files));\n }\n },\n triggerFileInput() {\n if (!config.sessionDocumentsEnabled || this.isDocumentOperationPending) return;\n var fileInput = document.getElementById('ai-chat-doc-input');\n if (fileInput) fileInput.click();\n },\n handleFileInputChange(e) {\n var files = e.target.files ? Array.from(e.target.files) : [];\n if (files && files.length > 0) {\n this.uploadFiles(files);\n }\n e.target.value = '';\n },\n queueDocumentOperation(operation) {\n var self = this;\n var previousOperation = this.documentOperationQueue || Promise.resolve();\n var nextOperation = previousOperation\n .catch(function () { })\n .then(async function () {\n self.isDocumentOperationPending = true;\n try {\n return await operation();\n } finally {\n self.isDocumentOperationPending = false;\n }\n });\n\n this.documentOperationQueue = nextOperation.finally(function () {\n if (self.documentOperationQueue === nextOperation) {\n self.documentOperationQueue = null;\n }\n });\n\n return this.documentOperationQueue;\n },\n async uploadFiles(files) {\n if (!config.uploadDocumentUrl) return;\n\n var filesToUpload = Array.isArray(files) ? files.slice() : Array.from(files || []);\n if (filesToUpload.length === 0) return;\n\n return this.queueDocumentOperation(async () => {\n var sessionId = this.getSessionId();\n var profileId = this.getProfileId();\n\n if (!sessionId) {\n try {\n sessionId = await this.ensureSessionForDocuments(profileId);\n } catch (err) {\n console.error('Failed to create a chat session for document upload:', err);\n this.uploadErrors = [{ fileName: '', error: 'Could not create a chat session for the upload.' }];\n this.renderDocumentBar();\n return;\n }\n }\n\n if (!sessionId) {\n console.warn('Cannot upload documents without a session or profile.');\n this.uploadErrors = [{ fileName: '', error: 'Could not create a chat session for the upload.' }];\n this.renderDocumentBar();\n return;\n }\n\n this.isUploading = true;\n this.uploadErrors = [];\n this.renderDocumentBar();\n try {\n var formData = new FormData();\n formData.append('sessionId', sessionId);\n for (var i = 0; i < filesToUpload.length; i++) {\n formData.append('files', filesToUpload[i]);\n }\n\n var response = await fetch(config.uploadDocumentUrl, {\n method: 'POST',\n body: formData\n });\n\n if (!response.ok) {\n var errorText = await response.text();\n var uploadError = this.extractReadableErrorMessage(errorText, 'Upload failed. Please try again.');\n console.error('Upload failed:', errorText);\n this.uploadErrors = [{ fileName: '', error: uploadError }];\n return;\n }\n\n var result = await response.json();\n\n if (result.sessionId && result.sessionId !== this.getSessionId()) {\n this.initializeSession(result.sessionId);\n }\n\n if (Array.isArray(result.documents)) {\n this.documents = result.documents;\n } else if (result.uploaded && result.uploaded.length > 0) {\n this.documents = this.documents.concat(result.uploaded);\n }\n\n if (result.failed && result.failed.length > 0) {\n this.uploadErrors = result.failed;\n }\n } catch (err) {\n console.error('Upload error:', err);\n this.uploadErrors = [{ fileName: '', error: 'Upload failed. Please try again.' }];\n\n if (this.getSessionId()) {\n this.reloadCurrentSession();\n }\n } finally {\n this.isUploading = false;\n this.renderDocumentBar();\n }\n });\n },\n async removeDocument(doc) {\n if (!config.removeDocumentUrl) return;\n\n return this.queueDocumentOperation(async () => {\n try {\n var sessionId = this.getSessionId();\n var response = await fetch(config.removeDocumentUrl, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ itemId: sessionId, documentId: doc.documentId })\n });\n\n if (response.ok) {\n var result = await response.json();\n\n if (Array.isArray(result.documents)) {\n this.documents = result.documents;\n } else {\n var idx = this.documents.indexOf(doc);\n if (idx > -1) {\n this.documents.splice(idx, 1);\n }\n }\n } else {\n var errorText = await response.text();\n var removeError = this.extractReadableErrorMessage(errorText, 'Failed to remove document. Please try again.');\n console.error('Failed to remove document:', response.status, errorText);\n this.uploadErrors = [{ fileName: doc.fileName || '', error: removeError }];\n if (sessionId) {\n this.reloadCurrentSession();\n }\n this.renderDocumentBar();\n }\n } catch (err) {\n console.error('Remove document error:', err);\n this.uploadErrors = [{ fileName: doc.fileName || '', error: 'Failed to remove document. Please try again.' }];\n if (this.getSessionId()) {\n this.reloadCurrentSession();\n }\n this.renderDocumentBar();\n }\n });\n },\n formatFileSize(bytes) {\n if (bytes < 1024) return bytes + ' B';\n if (bytes < 1024 * 1024) return (bytes / 1024).toFixed(1) + ' KB';\n return (bytes / (1024 * 1024)).toFixed(1) + ' MB';\n },\n renderDocumentBar() {\n if (!this.documentBar) return;\n\n if (!config.sessionDocumentsEnabled) {\n this.documentBar.classList.add('d-none');\n return;\n }\n\n this.documentBar.classList.remove('d-none');\n\n var html = '
';\n html += '
';\n\n for (var i = 0; i < this.documents.length; i++) {\n var doc = this.documents[i];\n var name = doc.fileName || 'Document';\n if (name.length > 20) name = name.substring(0, 17) + '...';\n html += '';\n html += ' ';\n html += this.escapeHtml(name);\n html += ' ';\n html += '';\n }\n\n for (var m = 0; m < this.uploadErrors.length; m++) {\n var failedItem = this.uploadErrors[m];\n var failedName = failedItem.fileName || 'File';\n var errorMsg = failedItem.error || 'Upload failed';\n if (failedName.length > 15) failedName = failedName.substring(0, 12) + '...';\n html += '';\n html += ' ';\n html += this.escapeHtml(failedName);\n html += ' ';\n html += '';\n }\n\n if (this.isUploading) {\n html += '';\n html += ' Uploading...';\n html += '';\n }\n\n html += '';\n html += '
';\n if (config.supportedExtensionsText) {\n html += '
Supported formats: ' + this.escapeHtml(config.supportedExtensionsText) + '
';\n }\n\n html += '
';\n\n this.documentBar.replaceChildren(DOMPurify.sanitize(html, { RETURN_DOM_FRAGMENT: true }));\n\n // Bind remove handlers\n var self = this;\n var closeButtons = this.documentBar.querySelectorAll('[data-doc-index]');\n for (var j = 0; j < closeButtons.length; j++) {\n closeButtons[j].addEventListener('click', (function (idx) {\n return function (e) {\n e.preventDefault();\n e.stopPropagation();\n if (self.isDocumentOperationPending) {\n return;\n }\n\n var docToRemove = self.documents[idx];\n if (docToRemove) self.removeDocument(docToRemove);\n };\n })(parseInt(closeButtons[j].getAttribute('data-doc-index'))));\n }\n\n // Bind error dismiss handlers\n var errorCloseButtons = this.documentBar.querySelectorAll('[data-error-index]');\n for (var n = 0; n < errorCloseButtons.length; n++) {\n errorCloseButtons[n].addEventListener('click', (function (idx) {\n return function (e) {\n e.preventDefault();\n e.stopPropagation();\n self.uploadErrors.splice(idx, 1);\n self.renderDocumentBar();\n };\n })(parseInt(errorCloseButtons[n].getAttribute('data-error-index'))));\n }\n\n // Bind add button\n var addBtn = this.documentBar.querySelector('.ai-chat-doc-add-btn');\n if (addBtn) {\n addBtn.addEventListener('click', function (e) {\n e.preventDefault();\n if (self.isDocumentOperationPending) {\n return;\n }\n self.triggerFileInput();\n });\n }\n },\n escapeHtml(text) {\n var div = document.createElement('div');\n div.textContent = text;\n return div.innerHTML;\n },\n extractReadableErrorMessage(errorText, fallbackMessage) {\n if (!errorText || typeof errorText !== 'string') {\n return fallbackMessage;\n }\n\n var trimmed = errorText.trim();\n if (!trimmed) {\n return fallbackMessage;\n }\n\n if (trimmed.startsWith('{') || trimmed.startsWith('[')) {\n try {\n var parsed = JSON.parse(trimmed);\n var message = parsed?.error || parsed?.message || parsed?.title || parsed?.detail;\n return typeof message === 'string' && message.trim()\n ? message.trim()\n : fallbackMessage;\n } catch (err) {\n return fallbackMessage;\n }\n }\n\n if (/<[^>]+>/.test(trimmed)) {\n return fallbackMessage;\n }\n\n return trimmed;\n },\n normalizeAssistantAppearance(appearance) {\n if (!appearance) {\n return null;\n }\n\n var label = typeof appearance.label === 'string' ? appearance.label.trim() : '';\n var icon = typeof appearance.icon === 'string' ? appearance.icon.trim() : '';\n var cssClass = typeof appearance.cssClass === 'string' ? appearance.cssClass.trim() : '';\n var disableStreamingAnimation = !!appearance.disableStreamingAnimation;\n\n if (!label && !icon && !cssClass && !disableStreamingAnimation) {\n return null;\n }\n\n return {\n label: label,\n icon: icon,\n cssClass: cssClass,\n disableStreamingAnimation: disableStreamingAnimation,\n };\n },\n getAssistantLabel(message) {\n var appearance = message ? this.normalizeAssistantAppearance(message.appearance) : null;\n return appearance && appearance.label ? appearance.label : this.assistantLabel;\n },\n getAssistantRoleClasses(message) {\n var appearance = message ? this.normalizeAssistantAppearance(message.appearance) : null;\n var classes = ['ai-chat-msg-role'];\n\n if (appearance && appearance.cssClass) {\n classes.push(appearance.cssClass);\n } else {\n classes.push('ai-chat-msg-role-assistant');\n }\n\n return classes;\n },\n getAssistantIconClasses(message, index) {\n var appearance = message ? this.normalizeAssistantAppearance(message.appearance) : null;\n return [this.shouldAnimateAssistantIcon(message, index) ? 'ai-streaming-icon' : 'ai-bot-icon', appearance && appearance.cssClass ? appearance.cssClass : ''];\n },\n getAssistantIcon(message) {\n var appearance = message ? this.normalizeAssistantAppearance(message.appearance) : null;\n return appearance && appearance.icon ? appearance.icon : 'fa fa-robot';\n },\n shouldAnimateAssistantIcon(message, index) {\n var appearance = message ? this.normalizeAssistantAppearance(message.appearance) : null;\n return !!message &&\n message.isStreaming &&\n index === this.lastAssistantIndex &&\n !(appearance && appearance.disableStreamingAnimation);\n },\n async startConnection() {\n this.connection = new signalR.HubConnectionBuilder()\n .withUrl(config.signalRHubUrl)\n .withAutomaticReconnect()\n .build();\n\n // Allow long-running operations (e.g., multi-step MCP tool calls)\n // without the client disconnecting prematurely.\n this.connection.serverTimeoutInMilliseconds = 600000;\n this.connection.keepAliveIntervalInMilliseconds = 15000;\n\n this.connection.on(\"LoadSession\", (data) => {\n this.initializeSession(data.sessionId, true);\n this.messages = [];\n this.documents = data.documents || [];\n this.uploadErrors = [];\n\n (data.messages ?? []).forEach(msg => {\n this.addMessage(msg);\n\n this.$nextTick(() => {\n renderChartsInMessage(msg);\n });\n });\n\n // Update feedback icons in the DOM after all messages have rendered.\n this.$nextTick(() => {\n this.refreshAllFeedbackIcons();\n });\n\n // When the session is new (no messages) and an initial prompt is configured,\n // automatically send it as the first user message to trigger an AI response.\n if (this.messages.length === 0 && config.initialPrompt) {\n this.prompt = config.initialPrompt;\n this.sendMessage();\n }\n });\n\n this.connection.on(\"ReceiveError\", (error) => {\n console.error(\"SignalR Error: \", error);\n\n if (this.isRecording) {\n this.stopRecording();\n }\n\n if (widgetBehavior && typeof widgetBehavior.handleReceiveError === 'function') {\n widgetBehavior.handleReceiveError(this, error, config);\n }\n });\n\n this.connection.on(\"MessageRated\", (messageId, userRating) => {\n var msg = this.messages.find(m => m.id === messageId);\n if (msg) {\n msg.userRating = userRating;\n }\n });\n\n this.connection.on(\"ReceiveTranscript\", (sessionId, text, isFinal) => {\n if (this.isConversationMode) {\n if (!isFinal && text) {\n this._conversationPartialTranscript = text;\n var escaped = text.replace(/&/g, '&').replace(//g, '>');\n var html = '

' + escaped + '

';\n\n // Show partial transcript as a live user message.\n if (!this._conversationPartialMessage) {\n this.hidePlaceholder();\n this._conversationPartialMessage = {\n role: 'user',\n content: text,\n htmlContent: html,\n isPartial: true\n };\n this.messages.push(this._conversationPartialMessage);\n } else {\n this._conversationPartialMessage.content = text;\n this._conversationPartialMessage.htmlContent = html;\n }\n this.scrollToBottom();\n }\n return;\n }\n\n if (text && !this._audioInputSent) {\n this.prompt = this.preRecordingPrompt + text;\n if (this.inputElement) {\n this.inputElement.value = this.prompt;\n this.inputElement.dispatchEvent(new Event('input'));\n }\n }\n });\n\n this.connection.on(\"ReceiveConversationUserMessage\", (sessionId, text) => {\n if (text) {\n this.stopAudio();\n\n // If there's an interrupted assistant message still streaming,\n // mark it as done to stop the spinner animation.\n if (this._conversationAssistantMessage) {\n var oldMsg = this.messages[this._conversationAssistantMessage.index];\n if (oldMsg) {\n oldMsg.isStreaming = false;\n }\n this._conversationAssistantMessage = null;\n }\n\n // Replace the partial transcript message with the final one.\n if (this._conversationPartialMessage) {\n var escaped = text.replace(/&/g, '&').replace(//g, '>');\n this._conversationPartialMessage.content = text;\n this._conversationPartialMessage.htmlContent = '

' + escaped + '

';\n this._conversationPartialMessage.isPartial = false;\n this._conversationPartialMessage = null;\n } else {\n this.addMessage({\n role: 'user',\n content: text\n });\n }\n this.scrollToBottom();\n }\n });\n\n this.connection.on(\"ReceiveConversationAssistantToken\", (sessionId, messageId, token, responseId, references, appearance) => {\n if (!this._conversationAssistantMessage) {\n this.stopAudio();\n this.hideTypingIndicator();\n\n // Ensure no stale streaming indicators remain from prior messages.\n for (var j = 0; j < this.messages.length; j++) {\n if (this.messages[j].isStreaming) {\n this.messages[j].isStreaming = false;\n }\n }\n\n var msgIndex = this.messages.length;\n var newMessage = {\n id: messageId,\n role: \"assistant\",\n content: \"\",\n htmlContent: \"\",\n isStreaming: true,\n userRating: null,\n appearance: this.normalizeAssistantAppearance(appearance),\n references: {},\n };\n this.messages.push(newMessage);\n this._conversationAssistantMessage = { index: msgIndex, content: '' };\n }\n\n this._conversationAssistantMessage.content += token;\n var msg = this.messages[this._conversationAssistantMessage.index];\n if (msg) {\n if (!msg.appearance) {\n msg.appearance = this.normalizeAssistantAppearance(appearance);\n }\n msg.rawContent = this._conversationAssistantMessage.content;\n msg.references = normalizeReferences(Object.assign({}, msg.references || {}, references || {}));\n updateMessagePresentation(msg, msg.references);\n this.$nextTick(() => {\n renderChartsInMessage(msg);\n this.scrollToBottom();\n });\n }\n });\n\n this.connection.on(\"ReceiveConversationAssistantComplete\", (sessionId, messageId, references) => {\n if (this._conversationAssistantMessage) {\n var msg = this.messages[this._conversationAssistantMessage.index];\n if (msg) {\n msg.isStreaming = false;\n msg.references = normalizeReferences(Object.assign({}, msg.references || {}, references || {}));\n updateMessagePresentation(msg, msg.references);\n }\n this._conversationAssistantMessage = null;\n }\n });\n\n this.connection.on(\"ReceiveAudioChunk\", (sessionId, base64Audio, contentType) => {\n if (base64Audio) {\n const binaryString = atob(base64Audio);\n const bytes = new Uint8Array(binaryString.length);\n for (let i = 0; i < binaryString.length; i++) {\n bytes[i] = binaryString.charCodeAt(i);\n }\n this.audioChunks.push(bytes);\n }\n });\n\n this.connection.on(\"ReceiveAudioComplete\", (sessionId) => {\n this.playCollectedAudio();\n });\n\n this.connection.on(\"ReceiveNotification\", (notification) => {\n this.receiveNotification(notification);\n });\n\n this.connection.on(\"UpdateNotification\", (notification) => {\n this.updateNotification(notification);\n });\n\n this.connection.on(\"RemoveNotification\", (notificationType) => {\n this.removeNotification(notificationType);\n });\n\n this.connection.onreconnecting(() => {\n console.warn(\"SignalR: reconnecting...\");\n });\n\n this.connection.onreconnected(() => {\n console.info(\"SignalR: reconnected.\");\n\n if (this.isSessionStarted) {\n this.reloadCurrentSession();\n } else if (config.autoCreateSession) {\n this.startNewSession();\n }\n });\n\n this.connection.onclose((error) => {\n if (this.isNavigatingAway) {\n return;\n }\n\n if (error) {\n console.warn(\"SignalR connection closed with error:\", error.message || error);\n }\n });\n\n try {\n await this.connection.start();\n } catch (err) {\n console.error(\"SignalR Connection Error: \", err);\n }\n },\n addMessageInternal(message) {\n if (message.role === 'assistant') {\n message.appearance = this.normalizeAssistantAppearance(message.appearance);\n }\n\n if (message.content && !message.htmlContent) {\n message.htmlContent = parseMarkdownContent(message.content, message);\n }\n this.fireEvent(new CustomEvent(\"addingCoreAIPromotMessage\", { detail: { message: message } }));\n this.messages.push(message);\n\n this.$nextTick(() => {\n this.fireEvent(new CustomEvent(\"addedCoreAIPromotMessage\", { detail: { message: message } }));\n });\n },\n addMessage(message) {\n\n // Ensure userRating is always defined for Vue reactivity.\n if (message.userRating === undefined) {\n message.userRating = null;\n }\n\n if (message.content) {\n message.rawContent = message.rawContent ?? message.content;\n updateMessagePresentation(message, message.references);\n }\n\n this.addMessageInternal(message);\n this.hidePlaceholder();\n\n this.$nextTick(() => {\n // Render any pending charts once the DOM is updated\n renderChartsInMessage(message);\n this.scrollToBottom();\n });\n },\n addMessages(messages) {\n\n for (let i = 0; i < messages.length; i++) {\n this.addMessageInternal(messages[i]);\n }\n\n this.hidePlaceholder();\n this.$nextTick(() => {\n this.scrollToBottom();\n });\n },\n hidePlaceholder() {\n if (this.placeholder) {\n this.placeholder.classList.add('d-none');\n }\n this.isPlaceholderVisible = false;\n },\n showPlaceholder() {\n if (this.placeholder) {\n this.placeholder.classList.remove('d-none');\n }\n this.isPlaceholderVisible = true;\n },\n isOrchestratorAvailable() {\n return config.isOrchestratorAvailable !== false;\n },\n applyOrchestratorAvailability() {\n if (this.isOrchestratorAvailable()) {\n return true;\n }\n\n const unavailableMessage = config.orchestratorUnavailableMessage || \"This orchestrator is not currently available.\";\n\n if (this.inputElement) {\n this.inputElement.disabled = true;\n this.inputElement.value = '';\n this.inputElement.placeholder = unavailableMessage;\n }\n\n if (this.buttonElement) {\n this.buttonElement.disabled = true;\n }\n\n if (this.micButtonElement) {\n this.micButtonElement.disabled = true;\n this.micButtonElement.style.display = 'none';\n }\n\n if (this.conversationButtonElement) {\n this.conversationButtonElement.disabled = true;\n this.conversationButtonElement.style.display = 'none';\n }\n\n return false;\n },\n fireEvent(event) {\n document.dispatchEvent(event);\n },\n isIndicator(message) {\n return message.role === 'indicator';\n },\n sendMessage() {\n if (!this.applyOrchestratorAvailability()) {\n return;\n }\n\n let trimmedPrompt = this.prompt.trim();\n\n if (!trimmedPrompt) {\n return;\n }\n\n // Stop any active recording before sending.\n if (this.isRecording) {\n this.stopRecording();\n }\n\n // Prevent stale ReceiveTranscript events from repopulating the prompt.\n this._audioInputSent = true;\n\n // In single-response mode, clear all previous messages.\n if (this.singleResponseMode) {\n this.messages.splice(0, this.messages.length);\n }\n\n this.addMessage({\n role: 'user',\n content: trimmedPrompt\n });\n\n this.streamMessage(this.getProfileId(), trimmedPrompt, null);\n this.inputElement.value = '';\n this.prompt = '';\n },\n startRecording() {\n if (this.isRecording || !this.connection) {\n return;\n }\n\n navigator.mediaDevices.getUserMedia({ audio: { echoCancellation: true, noiseSuppression: true, autoGainControl: true } })\n .then(stream => {\n var mimeType = MediaRecorder.isTypeSupported('audio/ogg;codecs=opus')\n ? 'audio/ogg;codecs=opus'\n : MediaRecorder.isTypeSupported('audio/webm;codecs=opus')\n ? 'audio/webm;codecs=opus'\n : 'audio/webm';\n\n this.mediaRecorder = new MediaRecorder(stream, {\n mimeType: mimeType,\n audioBitsPerSecond: 128000,\n });\n\n this.preRecordingPrompt = this.prompt;\n this._audioInputSent = false;\n\n var subject = new signalR.Subject();\n var profileId = this.getProfileId();\n var sessionId = this.getSessionId() || '';\n var pendingChunk = Promise.resolve();\n\n this.mediaRecorder.addEventListener('dataavailable', (e) => {\n if (e.data && e.data.size > 0) {\n pendingChunk = pendingChunk.then(async () => {\n var data = await e.data.arrayBuffer();\n var uint8Array = new Uint8Array(data);\n var binaryString = uint8Array.reduce(function (str, byte) { return str + String.fromCharCode(byte); }, '');\n var base64 = btoa(binaryString);\n subject.next(base64);\n });\n }\n });\n\n this.mediaRecorder.addEventListener('stop', () => {\n stream.getTracks().forEach(track => track.stop());\n pendingChunk.then(() => subject.complete());\n });\n\n var language = navigator.language || document.documentElement.lang || 'en-US';\n this.connection.send(\"SendAudioStream\", profileId, sessionId, subject, mimeType, language);\n this.mediaRecorder.start(250);\n this.isRecording = true;\n this.updateMicButton();\n })\n .catch(err => {\n console.error('Microphone access denied:', err);\n });\n },\n stopRecording() {\n if (!this.isRecording || !this.mediaRecorder) {\n return;\n }\n\n this.mediaRecorder.stop();\n this.isRecording = false;\n this.updateMicButton();\n },\n toggleRecording() {\n if (this.isRecording) {\n this.stopRecording();\n } else {\n this.startRecording();\n }\n },\n updateMicButton() {\n if (!this.micButton) {\n return;\n }\n\n if (this.isRecording) {\n this.micButton.classList.add('stt-recording');\n this.micButton.innerHTML = '';\n } else {\n this.micButton.classList.remove('stt-recording');\n this.micButton.innerHTML = '';\n }\n },\n streamMessage(profileId, trimmedPrompt, sessionProfileId) {\n\n if (this.stream) {\n this.stream.dispose();\n this.stream = null;\n }\n\n this.streamingStarted();\n this.showTypingIndicator();\n this.autoScroll = true;\n\n var content = '';\n var references = {};\n var lastResponseId = null;\n\n // Get the index after showing typing indicator.\n var messageIndex = this.messages.length;\n var currentSessionId = this.getSessionId();\n\n this.stream = this.connection.stream(\"SendMessage\", profileId, trimmedPrompt, currentSessionId, sessionProfileId)\n .subscribe({\n next: (chunk) => {\n let message = this.messages[messageIndex];\n\n if (!message) {\n\n if (chunk.sessionId && !currentSessionId) {\n this.initializeSession(chunk.sessionId);\n }\n\n this.hideTypingIndicator();\n // Re-assign the index after hiding the typing indicator.\n messageIndex = this.messages.length;\n let newMessage = {\n id: chunk.messageId,\n role: \"assistant\",\n title: chunk.title,\n content: \"\",\n htmlContent: \"\",\n isStreaming: true,\n userRating: null,\n };\n\n this.messages.push(newMessage);\n\n message = newMessage;\n }\n\n if (chunk.title && (!message.title || message.title !== chunk.title)) {\n message.title = chunk.title;\n }\n\n if (chunk.references && typeof chunk.references === \"object\" && Object.keys(chunk.references).length) {\n\n for (const [key, value] of Object.entries(chunk.references)) {\n references[key] = normalizeReference(value) ?? {};\n }\n }\n\n if (chunk.content) {\n\n // When the responseId changes (e.g., after an internal tool call),\n // insert a line break to visually separate response segments.\n if (chunk.responseId && lastResponseId && chunk.responseId !== lastResponseId) {\n content += '\\n\\n';\n }\n\n if (chunk.responseId) {\n lastResponseId = chunk.responseId;\n }\n\n content += chunk.content;\n }\n\n // Update the existing message\n message.rawContent = content;\n updateMessagePresentation(message, references);\n\n this.messages[messageIndex] = message;\n\n this.$nextTick(() => {\n renderChartsInMessage(message);\n this.scrollToBottom();\n });\n },\n complete: () => {\n this.processReferences(references, messageIndex);\n this.streamingFinished();\n\n let msg = this.messages[messageIndex];\n if (msg) {\n msg.isStreaming = false;\n }\n\n if (!msg || !msg.content) {\n // No content received at all.\n this.hideTypingIndicator();\n }\n\n // Trigger text-to-speech only in conversation mode.\n if (this.isConversationMode && this.textToSpeechEnabled && msg && msg.content) {\n this.synthesizeSpeech(msg.content);\n }\n\n this.stream?.dispose();\n this.stream = null;\n },\n error: (err) => {\n this.processReferences(references, messageIndex);\n this.streamingFinished();\n\n let msg = this.messages[messageIndex];\n if (msg) {\n msg.isStreaming = false;\n }\n\n this.hideTypingIndicator();\n\n if (!this.isNavigatingAway) {\n this.addMessage(this.getServiceDownMessage());\n }\n\n this.stream?.dispose();\n this.stream = null;\n\n console.error(\"Stream error:\", err);\n }\n });\n },\n getServiceDownMessage() {\n let newMessage = {\n role: \"assistant\",\n content: \"Our service is currently unavailable. Please try again later. We apologize for the inconvenience.\",\n htmlContent: \"\",\n };\n\n return newMessage;\n },\n processReferences(references, messageIndex) {\n references = normalizeReferences(references);\n\n if (Object.keys(references).length) {\n\n let message = this.messages[messageIndex];\n message.rawContent = message.rawContent ?? message.content ?? '';\n updateMessagePresentation(message, references);\n\n this.messages[messageIndex] = message;\n\n this.$nextTick(() => {\n renderChartsInMessage(message);\n this.scrollToBottom();\n });\n }\n },\n streamingStarted() {\n var stopIcon = this.buttonElement.getAttribute('data-stop-icon');\n\n if (stopIcon) {\n this.buttonElement.replaceChildren(DOMPurify.sanitize(stopIcon, { RETURN_DOM_FRAGMENT: true }));\n }\n\n if (this.inputElement) {\n this.inputElement.setAttribute('disabled', 'disabled');\n }\n },\n streamingFinished() {\n var startIcon = this.buttonElement.getAttribute('data-start-icon');\n\n if (startIcon) {\n this.buttonElement.replaceChildren(DOMPurify.sanitize(startIcon, { RETURN_DOM_FRAGMENT: true }));\n }\n\n if (this.inputElement) {\n this.inputElement.removeAttribute('disabled');\n this.inputElement.focus();\n }\n\n // Directly manipulate the DOM to stop all streaming animations.\n if (this.chatContainer) {\n var icons = this.chatContainer.querySelectorAll('.ai-streaming-icon');\n for (var i = 0; i < icons.length; i++) {\n icons[i].classList.remove('ai-streaming-icon');\n icons[i].classList.add('ai-bot-icon');\n }\n }\n\n // Also update Vue data for consistency.\n for (var i = 0; i < this.messages.length; i++) {\n if (this.messages[i].isStreaming) {\n this.messages[i].isStreaming = false;\n }\n }\n },\n handleExternalTtsStop(e) {\n if (e?.detail?.sourceId === this.ttsInstanceId) {\n return;\n }\n\n this.stopAudio(false);\n },\n updateTtsPlaybackButtons() {\n if (!this.chatContainer) {\n return;\n }\n\n var buttons = this.chatContainer.querySelectorAll('[data-tts-message-index]');\n\n buttons.forEach(button => {\n var buttonIndex = Number(button.getAttribute('data-tts-message-index'));\n var isPlaying = buttonIndex === this.ttsPlayingMessageIndex;\n\n button.classList.toggle('tts-playing', isPlaying);\n button.setAttribute('title', isPlaying ? 'Pause audio' : 'Read aloud');\n });\n },\n updateCopyButtons() {\n if (!this.chatContainer) {\n return;\n }\n\n var buttons = this.chatContainer.querySelectorAll('[data-copy-message-index]');\n\n buttons.forEach(button => {\n var buttonIndex = Number(button.getAttribute('data-copy-message-index'));\n var isCopied = buttonIndex === this.copiedMessageIndex;\n var iconHtml = isCopied\n ? ''\n : '';\n\n button.classList.toggle('text-success', isCopied);\n button.classList.toggle('text-secondary', !isCopied);\n button.setAttribute('title', isCopied ? this.copiedTitle : this.copyTitle);\n button.replaceChildren(DOMPurify.sanitize(iconHtml, { RETURN_DOM_FRAGMENT: true }));\n });\n },\n setCopyButtonState(button, isCopied) {\n if (!button) {\n return;\n }\n\n var iconHtml = isCopied\n ? ''\n : '';\n\n button.classList.toggle('text-success', isCopied);\n button.classList.toggle('text-secondary', !isCopied);\n button.setAttribute('title', isCopied ? this.copiedTitle : this.copyTitle);\n button.replaceChildren(DOMPurify.sanitize(iconHtml, { RETURN_DOM_FRAGMENT: true }));\n },\n synthesizeSpeech(text, cacheIndex) {\n if (!this.textToSpeechEnabled || !text || !this.connection) {\n return;\n }\n\n this.audioChunks = [];\n this.isPlayingAudio = true;\n this._ttsCacheIndex = cacheIndex !== undefined ? cacheIndex : -1;\n\n this.connection.invoke(\"SynthesizeSpeech\", this.getProfileId(), this.getSessionId(), text, this.ttsVoiceName)\n .catch(err => {\n console.error(\"TTS synthesis error:\", err);\n this.isPlayingAudio = false;\n this.ttsPlayingMessageIndex = -1;\n this._ttsCacheIndex = -1;\n this.$nextTick(() => this.updateTtsPlaybackButtons());\n });\n },\n toggleMessageTts(message, index) {\n if (this.ttsPlayingMessageIndex === index) {\n this.stopAudio();\n return;\n }\n\n this.stopAudio(false);\n window.dispatchEvent(new CustomEvent('crestapps-ai-chat-stop-tts', {\n detail: { sourceId: this.ttsInstanceId }\n }));\n this.ttsPlayingMessageIndex = index;\n this.$nextTick(() => this.updateTtsPlaybackButtons());\n\n if (this.ttsAudioCache[index]) {\n this.playAudioBlob(this.ttsAudioCache[index]);\n return;\n }\n\n this.synthesizeSpeech(message.content, index);\n },\n playCollectedAudio() {\n if (this.audioChunks.length === 0) {\n if (!this.currentAudioElement && this.audioPlayQueue.length === 0) {\n this.isPlayingAudio = false;\n this.ttsPlayingMessageIndex = -1;\n this.$nextTick(() => this.updateTtsPlaybackButtons());\n }\n return;\n }\n\n const totalLength = this.audioChunks.reduce((sum, chunk) => sum + chunk.length, 0);\n const combined = new Uint8Array(totalLength);\n let offset = 0;\n for (const chunk of this.audioChunks) {\n combined.set(chunk, offset);\n offset += chunk.length;\n }\n this.audioChunks = [];\n\n const blob = new Blob([combined], { type: 'audio/mp3' });\n\n if (this._ttsCacheIndex >= 0) {\n this.ttsAudioCache[this._ttsCacheIndex] = blob;\n this._ttsCacheIndex = -1;\n }\n\n // If audio is already playing, queue this blob for sequential playback.\n if (this.currentAudioElement) {\n this.audioPlayQueue.push(blob);\n return;\n }\n\n this.playAudioBlob(blob);\n },\n playAudioBlob(blob) {\n const url = URL.createObjectURL(blob);\n const audio = new Audio(url);\n\n this.currentAudioUrl = url;\n this.currentAudioElement = audio;\n this.isPlayingAudio = true;\n\n audio.addEventListener('ended', () => {\n this.currentAudioElement = null;\n this.currentAudioUrl = null;\n URL.revokeObjectURL(url);\n this.playNextInQueue();\n });\n\n audio.addEventListener('error', () => {\n this.currentAudioElement = null;\n this.currentAudioUrl = null;\n URL.revokeObjectURL(url);\n this.playNextInQueue();\n });\n\n audio.play().catch(err => {\n console.error(\"Audio playback error:\", err);\n this.currentAudioElement = null;\n this.currentAudioUrl = null;\n URL.revokeObjectURL(url);\n this.audioPlayQueue = [];\n this.isPlayingAudio = false;\n this.ttsPlayingMessageIndex = -1;\n this.$nextTick(() => this.updateTtsPlaybackButtons());\n });\n },\n playNextInQueue() {\n if (this.audioPlayQueue.length > 0) {\n var nextBlob = this.audioPlayQueue.shift();\n this.playAudioBlob(nextBlob);\n } else {\n this.isPlayingAudio = false;\n this.ttsPlayingMessageIndex = -1;\n this.$nextTick(() => this.updateTtsPlaybackButtons());\n this.conversationModeOnAudioEnded();\n }\n },\n stopAudio() {\n if (this.currentAudioElement) {\n this.currentAudioElement.pause();\n this.currentAudioElement.currentTime = 0;\n this.currentAudioElement = null;\n }\n if (this.currentAudioUrl) {\n URL.revokeObjectURL(this.currentAudioUrl);\n this.currentAudioUrl = null;\n }\n this.audioChunks = [];\n this.audioPlayQueue = [];\n this.isPlayingAudio = false;\n this.ttsPlayingMessageIndex = -1;\n this.$nextTick(() => this.updateTtsPlaybackButtons());\n },\n toggleConversationMode() {\n if (this.isConversationMode) {\n this.stopConversationMode();\n } else {\n this.startConversationMode();\n }\n },\n startConversationMode() {\n if (!this.conversationModeEnabled || this.isConversationMode || !this.connection) {\n return;\n }\n\n this.isConversationMode = true;\n this.updateConversationButton();\n this._conversationPartialTranscript = '';\n this._conversationAssistantMessage = null;\n this._conversationPartialMessage = null;\n\n // Remove any previous conversation ended notification.\n this.removeNotification('conversation-ended');\n navigator.mediaDevices.getUserMedia({ audio: { echoCancellation: true, noiseSuppression: true, autoGainControl: true } })\n .then(stream => {\n var mimeType = MediaRecorder.isTypeSupported('audio/ogg;codecs=opus')\n ? 'audio/ogg;codecs=opus'\n : MediaRecorder.isTypeSupported('audio/webm;codecs=opus')\n ? 'audio/webm;codecs=opus'\n : 'audio/webm';\n\n this.mediaRecorder = new MediaRecorder(stream, {\n mimeType: mimeType,\n audioBitsPerSecond: 128000,\n });\n\n this._conversationSubject = new signalR.Subject();\n this._conversationStream = stream;\n\n // Create an AnalyserNode for volume-based interrupt detection.\n // During TTS playback, detect when the user speaks above\n // the threshold to stop TTS (interrupt). Audio chunks are\n // always forwarded — browser echo cancellation handles\n // speaker echo so the STT stream has no gaps.\n var AudioCtx = window.AudioContext || window.webkitAudioContext;\n if (AudioCtx) {\n this._conversationAudioCtx = new AudioCtx();\n this._conversationAnalyser = this._conversationAudioCtx.createAnalyser();\n this._conversationAnalyser.fftSize = 256;\n var micSource = this._conversationAudioCtx.createMediaStreamSource(stream);\n micSource.connect(this._conversationAnalyser);\n }\n\n var pendingChunk = Promise.resolve();\n var analyser = this._conversationAnalyser;\n var interruptVolumeThreshold = 30;\n\n this.mediaRecorder.addEventListener('dataavailable', (e) => {\n if (e.data && e.data.size > 0) {\n // During TTS playback, check mic volume to detect\n // user interruption (speaking above threshold).\n if (this.isPlayingAudio && analyser) {\n var freqData = new Uint8Array(analyser.frequencyBinCount);\n analyser.getByteFrequencyData(freqData);\n var sum = 0;\n for (var k = 0; k < freqData.length; k++) { sum += freqData[k]; }\n var avg = sum / freqData.length;\n\n if (avg >= interruptVolumeThreshold) {\n // User is speaking — interrupt TTS playback.\n this.stopAudio();\n }\n }\n\n // Always send audio to STT — browser echo cancellation\n // handles speaker echo; continuous audio avoids gaps\n // that increase recognition latency.\n pendingChunk = pendingChunk.then(async () => {\n var data = await e.data.arrayBuffer();\n var uint8Array = new Uint8Array(data);\n var binaryString = uint8Array.reduce(function (str, byte) { return str + String.fromCharCode(byte); }, '');\n var base64 = btoa(binaryString);\n try {\n this._conversationSubject.next(base64);\n } catch (err) {\n // Subject may have been completed already.\n }\n });\n }\n });\n\n this.mediaRecorder.addEventListener('stop', () => {\n stream.getTracks().forEach(track => track.stop());\n pendingChunk.then(() => {\n try {\n this._conversationSubject.complete();\n } catch (err) {\n // Already completed.\n }\n });\n });\n\n var profileId = this.getProfileId();\n var sessionId = this.getSessionId() || '';\n var language = navigator.language || document.documentElement.lang || 'en-US';\n\n this.connection.send(\"StartConversation\", profileId, sessionId, this._conversationSubject, mimeType, language);\n this.mediaRecorder.start(250);\n this.isRecording = true;\n })\n .catch(err => {\n console.error('Microphone access denied:', err);\n this.isConversationMode = false;\n this.updateConversationButton();\n });\n },\n stopConversationMode() {\n if (!this.isConversationMode) {\n return;\n }\n\n this.isConversationMode = false;\n this.updateConversationButton();\n\n // Signal the server to cancel all in-progress STT/TTS streams immediately.\n if (this.connection) {\n this.connection.invoke(\"StopConversation\").catch(function () { });\n }\n\n if (this.isRecording && this.mediaRecorder) {\n this.mediaRecorder.stop();\n this.isRecording = false;\n }\n\n this.stopAudio();\n this._conversationPartialTranscript = '';\n this._conversationPartialMessage = null;\n\n // Clean up the AudioContext used for volume monitoring.\n if (this._conversationAudioCtx) {\n this._conversationAudioCtx.close().catch(function () { });\n this._conversationAudioCtx = null;\n this._conversationAnalyser = null;\n }\n\n // Mark any in-flight assistant message as done to stop the spinner.\n if (this._conversationAssistantMessage) {\n var msg = this.messages[this._conversationAssistantMessage.index];\n if (msg) {\n msg.isStreaming = false;\n }\n this._conversationAssistantMessage = null;\n }\n\n // Safety net: clear all lingering streaming indicators.\n for (var i = 0; i < this.messages.length; i++) {\n if (this.messages[i].isStreaming) {\n this.messages[i].isStreaming = false;\n }\n }\n\n // Show a \"conversation ended\" notification system message.\n this.receiveNotification({\n type: 'conversation-ended',\n content: 'Conversation ended.',\n icon: 'fa-solid fa-circle-check',\n dismissible: true,\n autoDismissMs: 5000\n });\n },\n updateConversationButton() {\n if (!this.conversationButton) {\n return;\n }\n\n if (this.isConversationMode) {\n this.conversationButton.classList.add('active', 'btn-primary');\n this.conversationButton.classList.remove('btn-dark', 'btn-outline-dark', 'btn-outline-secondary');\n this.conversationButton.title = this.conversationButton.getAttribute('data-end-title') || 'End Conversation';\n var endHtml = this.conversationButton.getAttribute('data-end-html');\n if (endHtml) {\n this.conversationButton.replaceChildren(DOMPurify.sanitize(endHtml, { RETURN_DOM_FRAGMENT: true }));\n }\n } else {\n this.conversationButton.classList.remove('active', 'btn-primary');\n this.conversationButton.classList.remove('btn-dark', 'btn-outline-secondary');\n this.conversationButton.classList.add('btn-outline-dark');\n this.conversationButton.blur();\n this.conversationButton.title = this.conversationButton.getAttribute('data-start-title') || 'Start Conversation';\n var startHtml = this.conversationButton.getAttribute('data-start-html');\n if (startHtml) {\n this.conversationButton.replaceChildren(DOMPurify.sanitize(startHtml, { RETURN_DOM_FRAGMENT: true }));\n }\n }\n },\n conversationModeSendPrompt() {\n // Legacy: only used by AudioInput mode's ReceiveTranscript.\n },\n conversationModeOnAudioEnded() {\n // Legacy: in conversation mode, audio playback continuation\n // is handled by the persistent stream. This method is only\n // called from playCollectedAudio for non-conversation TTS.\n },\n generatePrompt(element) {\n if (!element) {\n console.error('The element paramter is required.');\n\n return;\n }\n\n let templateProfileId = element.getAttribute('data-profile-id');\n let sessionId = this.getSessionId();\n let sessionProfileId = this.getProfileId();\n\n if (!templateProfileId || !sessionId) {\n\n console.error('The given element is missing data-profile-id or the session has not yet started.');\n return;\n }\n\n // streamMessage() already shows the typing indicator.\n this.streamMessage(templateProfileId, null, sessionProfileId);\n },\n createSessionUrl(baseUrl, param, value) {\n\n const fullUrl = baseUrl.toLowerCase().startsWith('http') ? baseUrl : window.location.origin + baseUrl;\n const url = new URL(fullUrl);\n\n url.searchParams.set(param, value);\n\n return url.toString();\n },\n showTypingIndicator() {\n this.addMessage({\n role: 'indicator',\n htmlContent: config.indicatorTemplate\n });\n },\n hideTypingIndicator() {\n const originalLength = this.messages.length;\n this.messages = this.messages.filter(msg => msg.role !== 'indicator');\n const removedCount = originalLength - this.messages.length;\n return removedCount;\n },\n receiveNotification(notification) {\n if (!notification || !notification.type) {\n return;\n }\n this.clearNotificationDismiss(notification.type);\n var existingIndex = this.notifications.findIndex(n => n.type === notification.type);\n if (existingIndex >= 0) {\n this.notifications.splice(existingIndex, 1, notification);\n } else {\n this.notifications.push(notification);\n }\n this.scheduleNotificationDismiss(notification);\n this.$nextTick(() => {\n this.scrollToBottom();\n });\n },\n updateNotification(notification) {\n if (!notification || !notification.type) {\n return;\n }\n this.clearNotificationDismiss(notification.type);\n var existingIndex = this.notifications.findIndex(n => n.type === notification.type);\n if (existingIndex >= 0) {\n this.notifications.splice(existingIndex, 1, notification);\n this.scheduleNotificationDismiss(notification);\n }\n },\n scheduleNotificationDismiss(notification) {\n if (!notification || !notification.type || !notification.autoDismissMs || notification.autoDismissMs <= 0) {\n return;\n }\n this.notificationDismissTimers[notification.type] = setTimeout(() => {\n this.removeNotification(notification.type);\n }, notification.autoDismissMs);\n },\n clearNotificationDismiss(notificationType) {\n var timerId = this.notificationDismissTimers[notificationType];\n if (!timerId) {\n return;\n }\n clearTimeout(timerId);\n delete this.notificationDismissTimers[notificationType];\n },\n removeNotification(notificationType) {\n this.clearNotificationDismiss(notificationType);\n this.notifications = this.notifications.filter(n => n.type !== notificationType);\n },\n dismissNotification(notificationType) {\n this.removeNotification(notificationType);\n },\n handleNotificationAction(notificationType, actionName) {\n if (!this.connection) {\n return;\n }\n var sessionId = this.getSessionId();\n this.connection.invoke(\"HandleNotificationAction\", sessionId, notificationType, actionName).catch(function (err) {\n console.error(\"Error handling notification action:\", err);\n });\n },\n scrollToBottom() {\n if (!this.autoScroll) {\n return;\n }\n setTimeout(() => {\n this.chatContainer.scrollTop = this.chatContainer.scrollHeight - this.chatContainer.clientHeight;\n }, 50);\n },\n handleUserInput(event) {\n this.prompt = event.target.value;\n },\n getProfileId() {\n return this.inputElement\n ? this.inputElement.getAttribute('data-profile-id')\n : null;\n },\n setSessionId(sessionId) {\n if (!this.inputElement) {\n return;\n }\n\n this.inputElement.setAttribute('data-session-id', sessionId || '');\n },\n resetSession() {\n this.stopRecording();\n this.rejectPendingSessionRequest('Session was reset.');\n this.setSessionId('');\n this.isSessionStarted = false;\n this.sessionRating = null;\n this.messages = [];\n this.documents = [];\n if (!config.autoCreateSession) {\n this.showPlaceholder();\n }\n\n if (config.autoCreateSession) {\n this.startNewSession();\n }\n\n if (widgetBehavior && typeof widgetBehavior.onSessionReset === 'function') {\n widgetBehavior.onSessionReset(this, config);\n }\n },\n startNewSession() {\n if (!this.applyOrchestratorAvailability()) {\n return;\n }\n\n const profileId = this.getProfileId();\n if (!profileId || !this.connection) {\n return;\n }\n\n this.requestNewSession(profileId).catch(err => console.error(err));\n },\n async ensureSessionForDocuments(profileId) {\n var sessionId = this.getSessionId();\n if (sessionId) {\n return sessionId;\n }\n\n if (!profileId || !this.connection) {\n return null;\n }\n\n return await this.requestNewSession(profileId);\n },\n requestNewSession(profileId) {\n if (this.pendingSessionPromise) {\n return this.pendingSessionPromise;\n }\n\n if (!profileId || !this.connection) {\n return Promise.resolve(null);\n }\n\n this.pendingSessionPromise = new Promise((resolve, reject) => {\n this.pendingSessionResolver = resolve;\n this.pendingSessionRejector = reject;\n this.pendingSessionTimeoutId = window.setTimeout(() => {\n this.rejectPendingSessionRequest('Timed out while creating a chat session.');\n }, 15000);\n });\n\n this.connection.invoke(\"StartSession\", profileId, null).catch(err => {\n this.rejectPendingSessionRequest(err);\n });\n\n return this.pendingSessionPromise;\n },\n resolvePendingSessionRequest(sessionId) {\n if (this.pendingSessionResolver) {\n this.pendingSessionResolver(sessionId);\n }\n\n this.clearPendingSessionRequest();\n },\n rejectPendingSessionRequest(error) {\n if (this.pendingSessionRejector) {\n this.pendingSessionRejector(error);\n }\n\n this.clearPendingSessionRequest();\n },\n clearPendingSessionRequest() {\n if (this.pendingSessionTimeoutId) {\n window.clearTimeout(this.pendingSessionTimeoutId);\n }\n\n this.pendingSessionPromise = null;\n this.pendingSessionResolver = null;\n this.pendingSessionRejector = null;\n this.pendingSessionTimeoutId = null;\n },\n initializeApp() {\n this.inputElement = document.querySelector(config.inputElementSelector);\n this.buttonElement = document.querySelector(config.sendButtonElementSelector);\n this.chatContainer = document.querySelector(config.chatContainerElementSelector);\n this.placeholder = document.querySelector(config.placeholderElementSelector);\n\n if (!this.inputElement || !this.buttonElement || !this.chatContainer || !this.placeholder) {\n console.error('AI chat app could not initialize because one or more required elements were not found.', {\n inputElementSelector: config.inputElementSelector,\n sendButtonElementSelector: config.sendButtonElementSelector,\n chatContainerElementSelector: config.chatContainerElementSelector,\n placeholderElementSelector: config.placeholderElementSelector\n });\n\n return false;\n }\n\n this.applyOrchestratorAvailability();\n\n const sessionId = this.getSessionId();\n if (!hasWidgetConfig && sessionId) {\n this.loadSession(sessionId);\n } else if (this.isOrchestratorAvailable() && config.autoCreateSession && !hasWidgetConfig && !sessionId) {\n this.startNewSession();\n }\n\n // Initialize document bar if enabled.\n if (config.sessionDocumentsEnabled && config.documentBarSelector) {\n this.documentBar = document.querySelector(config.documentBarSelector);\n if (this.documentBar) {\n this.renderDocumentBar();\n\n // Create hidden file input for document uploads.\n var fileInput = document.createElement('input');\n fileInput.type = 'file';\n fileInput.id = 'ai-chat-doc-input';\n fileInput.className = 'd-none';\n fileInput.multiple = true;\n if (config.allowedExtensions) {\n fileInput.accept = config.allowedExtensions;\n }\n fileInput.addEventListener('change', (e) => this.handleFileInputChange(e));\n this.documentBar.parentElement.appendChild(fileInput);\n\n // Set up drag-and-drop on the input area.\n var inputArea = this.inputElement ? this.inputElement.closest('.ai-admin-widget-input, .text-bg-light') : null;\n if (inputArea) {\n inputArea.addEventListener('dragover', (e) => this.handleDragOver(e));\n inputArea.addEventListener('dragleave', (e) => this.handleDragLeave(e));\n inputArea.addEventListener('drop', (e) => this.handleDrop(e));\n }\n }\n }\n\n // Pause auto-scroll when the user manually scrolls up during streaming.\n this.chatContainer.addEventListener('scroll', () => {\n if (!this.stream) {\n return;\n }\n const threshold = 30;\n const atBottom = this.chatContainer.scrollHeight - this.chatContainer.clientHeight - this.chatContainer.scrollTop <= threshold;\n this.autoScroll = atBottom;\n });\n\n this.inputElement.addEventListener('keydown', event => {\n\n if (this.stream != null) {\n return;\n }\n\n if (event.key === \"Enter\" && !event.shiftKey) {\n event.preventDefault();\n this.buttonElement.click();\n }\n });\n\n this.inputElement.addEventListener('input', (e) => {\n this.handleUserInput(e);\n\n if (e.target.value.trim()) {\n this.buttonElement.removeAttribute('disabled');\n } else {\n this.buttonElement.setAttribute('disabled', true);\n }\n });\n\n this.buttonElement.addEventListener('click', () => {\n\n if (this.stream != null) {\n this.stream.dispose();\n this.stream = null;\n\n this.streamingFinished();\n this.hideTypingIndicator();\n\n // Clean up: remove empty assistant message or stop streaming animation.\n if (this.messages.length > 0) {\n const lastMsg = this.messages[this.messages.length - 1];\n if (lastMsg.role === 'assistant' && !lastMsg.content) {\n this.messages.pop();\n } else if (lastMsg.isStreaming) {\n lastMsg.isStreaming = false;\n }\n }\n\n return;\n }\n\n this.sendMessage();\n });\n\n const promptGenerators = document.getElementsByClassName('profile-generated-prompt');\n\n for (var i = 0; i < promptGenerators.length; i++) {\n promptGenerators[i].addEventListener('click', (e) => {\n e.preventDefault();\n this.generatePrompt(e.target);\n });\n }\n\n const chatSessions = document.getElementsByClassName('chat-session-history-item');\n\n for (var i = 0; i < chatSessions.length; i++) {\n chatSessions[i].addEventListener('click', (e) => {\n e.preventDefault();\n\n var sessionId = e.target.getAttribute('data-session-id');\n\n if (!sessionId) {\n console.error('an element with the class chat-session-history-item with no data-session-id set.');\n\n return;\n }\n\n this.loadSession(sessionId);\n this.showChatScreen();\n });\n }\n\n const initialMessages = Array.isArray(config.messages) ? config.messages : [];\n\n for (let i = 0; i < initialMessages.length; i++) {\n this.addMessage(initialMessages[i]);\n }\n\n // Update feedback icons in the DOM after initial messages have rendered.\n this.$nextTick(() => {\n this.refreshAllFeedbackIcons();\n });\n\n // Delegate click for code block copy buttons.\n if (this.chatContainer) {\n this.chatContainer.addEventListener('click', (e) => {\n var btn = e.target.closest('.ai-code-copy-btn');\n if (!btn) {\n return;\n }\n\n var block = btn.closest('.ai-code-block') || btn.closest('pre');\n if (!block) {\n return;\n }\n\n var codeEl = block.querySelector('code');\n if (codeEl) {\n navigator.clipboard.writeText(codeEl.textContent);\n var copiedText = config.codeCopiedText || 'Copied!';\n btn.innerHTML = ' ' + copiedText;\n setTimeout(() => {\n btn.innerHTML = '';\n }, 2000);\n }\n });\n }\n\n // Initialize speech-to-text microphone button.\n if (this.speechToTextEnabled && config.micButtonElementSelector) {\n this.micButton = document.querySelector(config.micButtonElementSelector);\n if (this.micButton) {\n this.micButton.style.display = '';\n this.micButton.addEventListener('click', () => {\n this.toggleRecording();\n });\n }\n }\n\n // Initialize conversation mode button.\n if (this.conversationModeEnabled && config.conversationButtonElementSelector) {\n this.conversationButton = document.querySelector(config.conversationButtonElementSelector);\n if (this.conversationButton) {\n this.conversationButton.addEventListener('click', () => {\n this.toggleConversationMode();\n });\n }\n }\n\n return true;\n },\n loadSession(sessionId) {\n this.connection.invoke(\"LoadSession\", sessionId).catch(err => console.error(err));\n },\n reloadCurrentSession() {\n\n var sessionId = this.getSessionId();\n if (sessionId) {\n this.loadSession(sessionId);\n }\n },\n initializeSession(sessionId, force) {\n if (this.isSessionStarted && !force) {\n if (sessionId && this.getSessionId() === sessionId) {\n this.resolvePendingSessionRequest(sessionId);\n }\n\n return\n }\n this.fireEvent(new CustomEvent(\"initializingSessionCoreAIChat\", { detail: { sessionId: sessionId } }))\n this.setSessionId(sessionId);\n this.isSessionStarted = true;\n this.resolvePendingSessionRequest(sessionId);\n\n if (widgetBehavior && typeof widgetBehavior.onSessionInitialized === 'function') {\n widgetBehavior.onSessionInitialized(this, sessionId, config);\n }\n },\n getSessionId() {\n let sessionId = this.inputElement\n ? this.inputElement.getAttribute('data-session-id')\n : null;\n\n if (!sessionId && widgetBehavior && typeof widgetBehavior.resolveSessionId === 'function') {\n sessionId = widgetBehavior.resolveSessionId(this, config);\n }\n\n return sessionId;\n },\n clearCopiedMessageState() {\n if (this.copyResetTimeoutId) {\n window.clearTimeout(this.copyResetTimeoutId);\n this.copyResetTimeoutId = null;\n }\n\n if (this.activeCopyButton) {\n this.setCopyButtonState(this.activeCopyButton, false);\n this.activeCopyButton = null;\n }\n\n this.copiedMessageIndex = -1;\n },\n copyResponse(message, index, event) {\n const text = message && typeof message === 'object'\n ? message.copyContent ?? message.content ?? ''\n : message ?? '';\n const button = event?.currentTarget || event?.target?.closest?.('[data-copy-message-index]') || null;\n\n navigator.clipboard.writeText(text)\n .then(() => {\n this.clearCopiedMessageState();\n this.copiedMessageIndex = typeof index === 'number' ? index : -1;\n this.activeCopyButton = button;\n\n if (button) {\n this.setCopyButtonState(button, true);\n } else {\n this.$nextTick(() => this.updateCopyButtons());\n }\n\n this.copyResetTimeoutId = window.setTimeout(() => {\n this.clearCopiedMessageState();\n this.$nextTick(() => this.updateCopyButtons());\n }, Number(config.copyResetDelayMs) || 2000);\n })\n .catch(err => console.error('Failed to copy response:', err));\n },\n updateFeedbackIcons(container, userRating) {\n if (!container) {\n return;\n }\n\n var upBtn = container.querySelector('.rate-up-btn');\n var downBtn = container.querySelector('.rate-down-btn');\n\n // Keep feedback icons as simple span-based Font Awesome markup so\n // later state updates do not depend on i2svg replacement.\n if (upBtn) {\n var upClass = userRating === true ? 'fa-solid fa-thumbs-up' : 'fa-regular fa-thumbs-up';\n var upIcon = document.createElement('span');\n upIcon.className = upClass;\n upIcon.style.fontSize = '0.9rem';\n upBtn.textContent = '';\n upBtn.appendChild(upIcon);\n }\n\n if (downBtn) {\n var downClass = userRating === false ? 'fa-solid fa-thumbs-down' : 'fa-regular fa-thumbs-down';\n var downIcon = document.createElement('span');\n downIcon.className = downClass;\n downIcon.style.fontSize = '0.9rem';\n downBtn.textContent = '';\n downBtn.appendChild(downIcon);\n }\n },\n refreshAllFeedbackIcons() {\n var containers = this.$el.querySelectorAll('.ai-chat-message-assistant-feedback');\n\n for (var i = 0; i < containers.length; i++) {\n var msgId = containers[i].getAttribute('data-message-id');\n var msg = this.messages.find(m => m.id === msgId);\n\n if (msg) {\n this.updateFeedbackIcons(containers[i], msg.userRating);\n }\n }\n },\n rateMessage(message, isPositive, event) {\n var sessionId = this.getSessionId();\n\n if (!sessionId || !message.id || !this.connection) {\n return;\n }\n\n // Toggle: clicking the same rating again clears it.\n var newRating = message.userRating === isPositive ? null : isPositive;\n message.userRating = newRating;\n\n // Find the feedback container by message ID for reliable DOM targeting.\n var feedbackContainer = this.$el.querySelector(\n '.ai-chat-message-assistant-feedback[data-message-id=\"' + message.id + '\"]'\n );\n\n this.updateFeedbackIcons(feedbackContainer, newRating);\n\n // Trigger spark animation after Font Awesome has re-processed icons.\n if (newRating !== null && feedbackContainer) {\n setTimeout(() => {\n var btnClass = isPositive ? '.rate-up-btn' : '.rate-down-btn';\n var btn = feedbackContainer.querySelector(btnClass);\n\n if (btn) {\n btn.classList.remove('spark-effect');\n void btn.offsetWidth;\n btn.classList.add('spark-effect');\n btn.addEventListener('animationend', function onEnd() {\n btn.removeEventListener('animationend', onEnd);\n btn.classList.remove('spark-effect');\n });\n }\n }, 50);\n }\n\n this.connection.invoke(\"RateMessage\", sessionId, message.id, isPositive).catch(function (err) {\n console.error('Failed to rate message:', err);\n });\n }\n },\n watch: {\n documents: {\n handler() {\n this.renderDocumentBar();\n if (widgetBehavior && typeof widgetBehavior.onDocumentsChanged === 'function') {\n widgetBehavior.onDocumentsChanged(this, this.documents, config);\n }\n },\n deep: true\n },\n isUploading() { this.renderDocumentBar(); },\n isDocumentOperationPending() { this.renderDocumentBar(); },\n isPlayingAudio() {\n // Reserved for future use — volume-based interrupt detection\n // no longer mutes tracks; browser echo cancellation handles echo.\n },\n copiedMessageIndex() {\n this.$nextTick(() => this.updateCopyButtons());\n },\n isConversationMode(active) {\n // Hide/show mic button.\n if (this.micButton) {\n this.micButton.style.display = active ? 'none' : (this.speechToTextEnabled ? '' : 'none');\n }\n\n // Hide/show send button.\n if (this.buttonElement) {\n this.buttonElement.style.display = active ? 'none' : '';\n }\n\n // Disable/enable textarea.\n if (this.inputElement) {\n this.inputElement.disabled = active;\n if (active) {\n this.inputElement.placeholder = '';\n }\n }\n }\n },\n mounted() {\n (async () => {\n await this.startConnection();\n const isInitialized = this.initializeApp();\n if (isInitialized && hasWidgetConfig && widgetBehavior && typeof widgetBehavior.onMounted === 'function') {\n widgetBehavior.onMounted(this, config);\n }\n\n this.$nextTick(() => {\n this.updateCopyButtons();\n refreshFontAwesomeIcons(this.$el);\n this.fontAwesomeObserver = observeFontAwesomeIcons(this.$el);\n });\n })();\n\n window.addEventListener('beforeunload', this.handleBeforeUnload);\n window.addEventListener('crestapps-ai-chat-stop-tts', this.handleExternalTtsStop);\n },\n beforeUnmount() {\n window.removeEventListener('beforeunload', this.handleBeforeUnload);\n window.removeEventListener('crestapps-ai-chat-stop-tts', this.handleExternalTtsStop);\n\n if (this.fontAwesomeObserver) {\n this.fontAwesomeObserver.disconnect();\n this.fontAwesomeObserver = null;\n }\n\n this.clearCopiedMessageState();\n this.stopAudio(false);\n\n if (this.stream) {\n this.stream.dispose();\n this.stream = null;\n }\n if (this.connection) {\n this.connection.stop();\n }\n\n if (widgetBehavior && typeof widgetBehavior.onBeforeUnmount === 'function') {\n widgetBehavior.onBeforeUnmount(this, config);\n }\n },\n template: config.messageTemplate\n };\n\n const app = Vue.createApp(appDefinition).mount(config.appElementSelector);\n\n if (widgetBehavior && typeof widgetBehavior.attach === 'function') {\n widgetBehavior.attach(app, config);\n }\n\n return app;\n };\n\n const autoInitializeSelector = '[data-coreai-chat-config],[data-coreai-chat-app-element-selector]';\n\n function getAttributeValue(element, attributeName) {\n const value = element.getAttribute(attributeName);\n return value === null || value === '' ? null : value;\n }\n\n function parseBooleanAttributeValue(value) {\n if (value === null || value === undefined) {\n return null;\n }\n\n if (typeof value === 'boolean') {\n return value;\n }\n\n const normalized = String(value).trim().toLowerCase();\n if (normalized === 'true') {\n return true;\n }\n\n if (normalized === 'false') {\n return false;\n }\n\n return null;\n }\n\n function parseJsonAttribute(element, attributeName, description) {\n const rawValue = getAttributeValue(element, attributeName);\n if (!rawValue) {\n return null;\n }\n\n try {\n return JSON.parse(rawValue);\n } catch (error) {\n console.error('Failed to parse ' + description + ' JSON.', error);\n return null;\n }\n }\n\n function buildConfigFromDataAttributes(element, options) {\n const settings = options || {};\n\n if (element.hasAttribute('data-coreai-chat-widget-container-selector') && settings.allowWidgetHost !== true) {\n return null;\n }\n\n const appElementSelector = getAttributeValue(element, 'data-coreai-chat-app-element-selector');\n if (!appElementSelector) {\n return null;\n }\n\n const config = {\n signalRHubUrl: getAttributeValue(element, 'data-coreai-chat-signalr-hub-url'),\n appElementSelector: appElementSelector,\n chatContainerElementSelector: getAttributeValue(element, 'data-coreai-chat-container-element-selector'),\n inputElementSelector: getAttributeValue(element, 'data-coreai-chat-input-element-selector'),\n sendButtonElementSelector: getAttributeValue(element, 'data-coreai-chat-send-button-element-selector'),\n placeholderElementSelector: getAttributeValue(element, 'data-coreai-chat-placeholder-element-selector'),\n messages: parseJsonAttribute(element, 'data-coreai-chat-messages', 'CoreAI chat messages') ?? undefined,\n chatMode: getAttributeValue(element, 'data-coreai-chat-mode'),\n micButtonElementSelector: getAttributeValue(element, 'data-coreai-chat-mic-button-element-selector'),\n conversationButtonElementSelector: getAttributeValue(element, 'data-coreai-chat-conversation-button-element-selector'),\n ttsVoiceName: getAttributeValue(element, 'data-coreai-chat-tts-voice-name'),\n documentBarSelector: getAttributeValue(element, 'data-coreai-chat-document-bar-selector'),\n uploadDocumentUrl: getAttributeValue(element, 'data-coreai-chat-upload-document-url'),\n removeDocumentUrl: getAttributeValue(element, 'data-coreai-chat-remove-document-url'),\n allowedExtensions: getAttributeValue(element, 'data-coreai-chat-allowed-extensions'),\n supportedExtensionsText: getAttributeValue(element, 'data-coreai-chat-supported-extensions-text'),\n existingDocuments: parseJsonAttribute(element, 'data-coreai-chat-existing-documents', 'CoreAI chat existing documents') ?? undefined,\n initialPrompt: getAttributeValue(element, 'data-coreai-chat-initial-prompt'),\n userLabel: getAttributeValue(element, 'data-coreai-chat-user-label'),\n assistantLabel: getAttributeValue(element, 'data-coreai-chat-assistant-label'),\n copyTitle: getAttributeValue(element, 'data-coreai-chat-copy-title'),\n copiedTitle: getAttributeValue(element, 'data-coreai-chat-copied-title'),\n };\n\n const booleanAttributes = {\n metricsEnabled: 'data-coreai-chat-metrics-enabled',\n textToSpeechEnabled: 'data-coreai-chat-text-to-speech-enabled',\n sessionDocumentsEnabled: 'data-coreai-chat-session-documents-enabled',\n autoCreateSession: 'data-coreai-chat-auto-create-session',\n singleResponseMode: 'data-coreai-chat-single-response-mode',\n };\n\n Object.keys(booleanAttributes).forEach(key => {\n const parsed = parseBooleanAttributeValue(getAttributeValue(element, booleanAttributes[key]));\n if (parsed !== null) {\n config[key] = parsed;\n }\n });\n\n return compactObject(config);\n }\n\n function buildConfigFromElement(element, options) {\n const jsonConfig = parseJsonAttribute(element, 'data-coreai-chat-config', 'CoreAI chat config');\n const attributeConfig = buildConfigFromDataAttributes(element, options);\n\n if (!jsonConfig && !attributeConfig) {\n return null;\n }\n\n return Object.assign({}, jsonConfig || {}, attributeConfig || {});\n }\n\n function initializeFromElement(element) {\n if (!element || element.dataset.coreAiChatInitialized === 'true') {\n return element ? element.__coreAIChatApp || null : null;\n }\n\n const config = buildConfigFromElement(element);\n if (!config) {\n return null;\n }\n\n const app = initialize(config);\n if (!app) {\n return null;\n }\n\n element.dataset.coreAiChatInitialized = 'true';\n element.__coreAIChatApp = app;\n\n return app;\n }\n\n function scanForAutoInitialization(root) {\n if (!root || typeof root.querySelectorAll !== 'function') {\n return;\n }\n\n if (typeof root.matches === 'function' && root.matches(autoInitializeSelector)) {\n initializeFromElement(root);\n }\n\n root.querySelectorAll(autoInitializeSelector).forEach(initializeFromElement);\n }\n\n function startAutoInitialization() {\n scanForAutoInitialization(document);\n\n if (typeof MutationObserver === 'undefined') {\n return;\n }\n\n const observer = new MutationObserver(mutations => {\n mutations.forEach(mutation => {\n mutation.addedNodes.forEach(node => {\n if (node && node.nodeType === 1) {\n scanForAutoInitialization(node);\n }\n });\n });\n });\n\n observer.observe(document.body, {\n childList: true,\n subtree: true,\n });\n }\n\n if (document.readyState === 'loading') {\n document.addEventListener('DOMContentLoaded', startAutoInitialization, { once: true });\n } else {\n startAutoInitialization();\n }\n\n return {\n initialize: initialize,\n initializeFromElement: initializeFromElement,\n buildConfigFromElement: buildConfigFromElement,\n };\n}();\n\n// Download chart as image via event delegation (DOMPurify strips inline onclick).\ndocument.addEventListener('click', function (e) {\n const btn = e.target.closest('.download-chart-btn');\n if (!btn) {\n return;\n }\n const chartId = btn.getAttribute('data-chart-id');\n const canvas = chartId ? document.getElementById(chartId) : null;\n if (!canvas) {\n console.error('Chart canvas not found:', chartId);\n return;\n }\n const link = document.createElement('a');\n link.download = 'chart-' + chartId + '.png';\n link.href = canvas.toDataURL('image/png');\n link.click();\n});\n\n// Intercept download clicks for data-URI images and convert to blob downloads.\ndocument.addEventListener('click', function (e) {\n const link = e.target.closest('.ai-download-image');\n if (!link) {\n return;\n }\n\n const container = link.closest('.generated-image-container');\n const img = container?.querySelector('img');\n if (!img) {\n return;\n }\n\n const src = img.src;\n if (!src || !src.startsWith('data:')) {\n return; // Normal URL – let the default behaviour handle it.\n }\n\n e.preventDefault();\n\n fetch(src)\n .then(function (res) { return res.blob(); })\n .then(function (blob) {\n const url = URL.createObjectURL(blob);\n const a = document.createElement('a');\n a.href = url;\n a.download = link.getAttribute('download') || 'generated-image.png';\n document.body.appendChild(a);\n a.click();\n document.body.removeChild(a);\n setTimeout(function () { URL.revokeObjectURL(url); }, 100);\n })\n .catch(function (err) { console.error('Failed to download image:', err); });\n});\n"]} +{"version":3,"sources":["ai-chat.js"],"names":["_excluded","_regenerator","e","t","r","Symbol","n","iterator","o","toStringTag","i","c","prototype","Generator","u","Object","create","_regeneratorDefine2","f","p","y","G","v","a","d","bind","length","l","TypeError","call","done","value","GeneratorFunction","GeneratorFunctionPrototype","getPrototypeOf","this","setPrototypeOf","__proto__","displayName","w","m","defineProperty","_invoke","enumerable","configurable","writable","asyncGeneratorStep","Promise","resolve","then","_asyncToGenerator","arguments","apply","_next","_throw","_toConsumableArray","_arrayWithoutHoles","_iterableToArray","_unsupportedIterableToArray","_nonIterableSpread","Array","from","isArray","_arrayLikeToArray","_objectWithoutProperties","_objectWithoutPropertiesLoose","getOwnPropertySymbols","indexOf","propertyIsEnumerable","hasOwnProperty","_createForOfIteratorHelper","_n","F","s","next","_slicedToArray","_arrayWithHoles","_iterableToArrayLimit","_nonIterableRest","toString","slice","constructor","name","test","push","_typeof","window","coreAIChatManager","defaultConfig","generatedImageAltText","generatedImageMaxWidth","downloadImageTitle","downloadChartTitle","downloadChartButtonText","userLabel","assistantLabel","thumbsUpTitle","thumbsDownTitle","copyTitle","copiedTitle","codeCopiedText","copyResetDelayMs","widget","chatWidgetContainer","chatWidgetStateName","chatHistorySection","showHistoryButton","closeHistoryButton","newChatButton","toggleButtonSelector","resetSizeButtonSelector","dragHandleSelector","enableDragging","enableResizing","persistLayout","defaultWidth","defaultHeight","minWidth","minHeight","messageTemplate","indicatorTemplate","sanitizeUrl","url","trimmed","trim","escapeHtmlEntities","text","span","document","createElement","textContent","innerHTML","refreshFontAwesomeIcons","root","fontAwesome","FontAwesome","nodeType","selector","matches","querySelector","containsFontAwesomePlaceholders","dom","i2svg","node","observeFontAwesomeIcons","MutationObserver","observer","mutations","forEach","mutation","addedNodes","observe","childList","subtree","normalizeReference","reference","_ref","_normalized$index","_ref2","_normalized$text","_ref3","_normalized$title","_ref4","_normalized$link","_ref5","_normalized$reference","_normalized$isGenerat","normalized","assign","index","Index","Text","title","Title","link","Link","referenceType","ReferenceType","isGenerated","IsGenerated","isDownloadCitationReference","toLowerCase","normalizeReferences","references","_i","_Object$entries","entries","_normalizeReference","_Object$entries$_i","key","getCitationLabel","updateMessagePresentation","message","messageReferences","rawContent","content","citationDisplay","processedContent","referenceEntries","citations","citedRefs","filter","_ref6","includes","generatedRefs","_ref8","_ref9","sort","_ref0","_ref1","b","_ref12","_ref13","_step","displayIndex","_iterator","_step$value","placeholder","concat","replaceAll","referenceKey","label","isDownload","err","_i2","_citations","citation","_step2","_iterator2","_step2$value","map","_ref16","buildCitationDisplay","displayContent","citationReferences","copyContent","_step3","_iterator3","_step4","_iterator4","trimEnd","buildCopyContent","htmlContent","parseMarkdownContent","renderer","marked","Renderer","data","href","code","lang","highlighted","hljs","getLanguage","highlight","language","_","highlightAuto","langDisplay","image","src","alt","maxWidth","chartCounter","_pendingCharts","renderChartsInMessage","charts","requestAnimationFrame","_step5","_iterator5","renderChartOnCanvas","chartId","config","canvas","getElementById","Chart","console","warn","offsetParent","__chartConfigs","_cfg$options","_cfg$options2","_cfg$options2$aspectR","_chartInstance","destroy","cfg","JSON","parse","options","responsive","maintainAspectRatio","aspectRatio","error","html","DOMPurify","sanitize","ADD_TAGS","ADD_ATTR","compactObject","source","fromEntries","_ref17","undefined","use","extensions","level","start","idx","tokenizer","extracted","token","jsonStart","depth","inString","escape","ch","jsonEnd","closeBracketIndex","startIndex","endIndex","json","substring","tryExtractChartMarker","type","raw","renderPendingCharts","configs","_i3","_Object$keys","keys","initialize","instanceConfig","normalizedInstanceConfig","normalizedWidgetConfig","template","encodedAssistantLabel","replace","resolveIndicatorTemplate","hasWidgetConfig","widgetBehavior","coreAIChatWidgetBehavior","signalRHubUrl","appElementSelector","chatContainerElementSelector","inputElementSelector","sendButtonElementSelector","appDefinition","inputElement","buttonElement","chatContainer","isSessionStarted","isPlaceholderVisible","isStreaming","isNavigatingAway","autoScroll","stream","messages","notifications","prompt","documents","existingDocuments","isUploading","isDocumentOperationPending","documentOperationQueue","uploadErrors","isDragOver","documentBar","metricsEnabled","isRecording","mediaRecorder","preRecordingPrompt","micButton","speechToTextEnabled","chatMode","textToSpeechEnabled","ttsVoiceName","audioChunks","audioPlayQueue","isPlayingAudio","currentAudioElement","currentAudioUrl","ttsButton","ttsPlayingMessageIndex","ttsAudioCache","ttsInstanceId","Math","random","singleResponseMode","conversationModeEnabled","conversationButton","isConversationMode","notificationDismissTimers","pendingSessionPromise","pendingSessionResolver","pendingSessionRejector","pendingSessionTimeoutId","copiedMessageIndex","copyResetTimeoutId","activeCopyButton","computed","lastAssistantIndex","role","methods","handleBeforeUnload","handleDragOver","sessionDocumentsEnabled","preventDefault","stopPropagation","inputArea","closest","classList","add","handleDragLeave","remove","handleDrop","dataTransfer","files","uploadFiles","triggerFileInput","fileInput","click","handleFileInputChange","target","queueDocumentOperation","operation","self","nextOperation","_callee","_context","_this","_callee3","filesToUpload","_context3","uploadDocumentUrl","_callee2","sessionId","profileId","formData","response","errorText","uploadError","result","_t","_t2","_context2","getSessionId","getProfileId","ensureSessionForDocuments","fileName","renderDocumentBar","FormData","append","fetch","method","body","ok","extractReadableErrorMessage","initializeSession","uploaded","failed","reloadCurrentSession","removeDocument","doc","_this2","_callee5","_context5","removeDocumentUrl","_callee4","removeError","_t3","_context4","headers","stringify","itemId","documentId","splice","status","formatFileSize","bytes","toFixed","escapeHtml","failedItem","failedName","errorMsg","supportedExtensionsText","replaceChildren","RETURN_DOM_FRAGMENT","closeButtons","querySelectorAll","j","addEventListener","docToRemove","parseInt","getAttribute","errorCloseButtons","addBtn","div","fallbackMessage","startsWith","parsed","detail","normalizeAssistantAppearance","appearance","icon","cssClass","disableStreamingAnimation","getAssistantLabel","getAssistantRoleClasses","classes","getAssistantIconClasses","shouldAnimateAssistantIcon","getAssistantIcon","startConnection","_this3","_callee6","_t4","_context6","connection","signalR","HubConnectionBuilder","withUrl","withAutomaticReconnect","build","serverTimeoutInMilliseconds","keepAliveIntervalInMilliseconds","on","_data$messages","msg","addMessage","$nextTick","refreshAllFeedbackIcons","initialPrompt","sendMessage","stopRecording","handleReceiveError","messageId","userRating","find","id","isFinal","_conversationPartialTranscript","_conversationPartialMessage","hidePlaceholder","isPartial","scrollToBottom","_audioInputSent","dispatchEvent","Event","stopAudio","_conversationAssistantMessage","oldMsg","escaped","responseId","hideTypingIndicator","msgIndex","newMessage","base64Audio","contentType","binaryString","atob","Uint8Array","charCodeAt","playCollectedAudio","notification","receiveNotification","updateNotification","notificationType","removeNotification","onreconnecting","onreconnected","info","onclose","addMessageInternal","_this4","fireEvent","CustomEvent","_message$rawContent","_this5","addMessages","_this6","showPlaceholder","isOrchestratorAvailable","applyOrchestratorAvailability","unavailableMessage","orchestratorUnavailableMessage","disabled","micButtonElement","style","display","conversationButtonElement","event","isIndicator","trimmedPrompt","streamMessage","startRecording","_this7","navigator","mediaDevices","getUserMedia","audio","echoCancellation","noiseSuppression","autoGainControl","mimeType","MediaRecorder","isTypeSupported","audioBitsPerSecond","subject","Subject","pendingChunk","size","_callee7","uint8Array","base64","_context7","arrayBuffer","reduce","str","byte","String","fromCharCode","btoa","getTracks","track","stop","complete","documentElement","send","updateMicButton","toggleRecording","sessionProfileId","_this8","dispose","streamingStarted","showTypingIndicator","lastResponseId","messageIndex","currentSessionId","subscribe","chunk","_i4","_Object$entries2","_normalizeReference2","_Object$entries2$_i","_this8$stream","processReferences","streamingFinished","synthesizeSpeech","_this8$stream2","getServiceDownMessage","_this9","_ref23","_message$rawContent2","stopIcon","setAttribute","startIcon","removeAttribute","focus","icons","handleExternalTtsStop","_e$detail","sourceId","updateTtsPlaybackButtons","_this0","button","isPlaying","Number","toggle","updateCopyButtons","_this1","isCopied","iconHtml","setCopyButtonState","cacheIndex","_this10","_ttsCacheIndex","invoke","toggleMessageTts","_this11","playAudioBlob","_this12","_step6","totalLength","sum","combined","offset","_iterator6","set","blob","Blob","_this13","URL","createObjectURL","Audio","revokeObjectURL","playNextInQueue","play","_this14","nextBlob","shift","conversationModeOnAudioEnded","_this15","pause","currentTime","toggleConversationMode","stopConversationMode","startConversationMode","_this16","updateConversationButton","_conversationSubject","_conversationStream","AudioCtx","AudioContext","webkitAudioContext","_conversationAudioCtx","_conversationAnalyser","createAnalyser","fftSize","createMediaStreamSource","connect","analyser","freqData","frequencyBinCount","getByteFrequencyData","k","_callee8","_context8","close","dismissible","autoDismissMs","endHtml","blur","startHtml","conversationModeSendPrompt","generatePrompt","element","templateProfileId","createSessionUrl","baseUrl","param","fullUrl","location","origin","searchParams","originalLength","_this17","clearNotificationDismiss","existingIndex","findIndex","scheduleNotificationDismiss","_this18","setTimeout","timerId","clearTimeout","dismissNotification","handleNotificationAction","actionName","_this19","scrollTop","scrollHeight","clientHeight","handleUserInput","setSessionId","resetSession","rejectPendingSessionRequest","sessionRating","onSessionReset","startNewSession","requestNewSession","_this20","_callee9","_context9","_this21","reject","resolvePendingSessionRequest","clearPendingSessionRequest","initializeApp","_this22","placeholderElementSelector","loadSession","documentBarSelector","className","multiple","allowedExtensions","accept","parentElement","appendChild","atBottom","shiftKey","lastMsg","pop","promptGenerators","getElementsByClassName","chatSessions","showChatScreen","initialMessages","btn","block","codeEl","clipboard","writeText","copiedText","micButtonElementSelector","conversationButtonElementSelector","force","onSessionInitialized","resolveSessionId","clearCopiedMessageState","copyResponse","_ref25","_message$copyContent","_event$target","_event$target$closest","_this23","currentTarget","updateFeedbackIcons","container","upBtn","downBtn","upClass","upIcon","fontSize","downClass","downIcon","containers","$el","msgId","rateMessage","isPositive","newRating","feedbackContainer","btnClass","offsetWidth","onEnd","removeEventListener","watch","handler","onDocumentsChanged","deep","_this24","active","mounted","_this25","_callee0","_context0","onMounted","fontAwesomeObserver","beforeUnmount","disconnect","onBeforeUnmount","app","Vue","createApp","mount","attach","autoInitializeSelector","getAttributeValue","attributeName","parseJsonAttribute","description","rawValue","buildConfigFromDataAttributes","_parseJsonAttribute","_parseJsonAttribute2","settings","hasAttribute","allowWidgetHost","booleanAttributes","parseBooleanAttributeValue","buildConfigFromElement","jsonConfig","attributeConfig","initializeFromElement","dataset","coreAiChatInitialized","__coreAIChatApp","scanForAutoInitialization","startAutoInitialization","readyState","once","download","toDataURL","img","res","removeChild"],"mappings":"AAKA,IAAIA,UAAY,CAAC,eACjB,SAASC,iLALT,IAAAC,EAAAC,EAAAC,EAAA,mBAAAC,OAAAA,OAAA,CAAA,EAAAC,EAAAF,EAAAG,UAAA,aAAAC,EAAAJ,EAAAK,aAAA,gBAAA,SAAAC,EAAAN,EAAAE,EAAAE,EAAAE,GAAA,IAAAC,EAAAL,GAAAA,EAAAM,qBAAAC,EAAAP,EAAAO,EAAAC,EAAAC,OAAAC,OAAAL,EAAAC,WAAA,OAAAK,oBAAAH,EAAA,UAAA,SAAAV,EAAAE,EAAAE,GAAA,IAAAE,EAAAC,EAAAG,EAAAI,EAAA,EAAAC,EAAAX,GAAA,GAAAY,GAAA,EAAAC,EAAA,CAAAF,EAAA,EAAAb,EAAA,EAAAgB,EAAApB,EAAAqB,EAAAC,EAAAN,EAAAM,EAAAC,KAAAvB,EAAA,GAAAsB,EAAA,SAAArB,EAAAC,GAAA,OAAAM,EAAAP,EAAAQ,EAAA,EAAAG,EAAAZ,EAAAmB,EAAAf,EAAAF,EAAAmB,CAAA,GAAA,SAAAC,EAAApB,EAAAE,GAAA,IAAAK,EAAAP,EAAAU,EAAAR,EAAAH,EAAA,GAAAiB,GAAAF,IAAAV,GAAAL,EAAAgB,EAAAO,OAAAvB,IAAA,CAAA,IAAAK,EAAAE,EAAAS,EAAAhB,GAAAqB,EAAAH,EAAAF,EAAAQ,EAAAjB,EAAA,GAAAN,EAAA,GAAAI,EAAAmB,IAAArB,KAAAQ,EAAAJ,GAAAC,EAAAD,EAAA,IAAA,GAAAC,EAAA,EAAA,IAAAD,EAAA,GAAAA,EAAA,GAAAR,GAAAQ,EAAA,IAAAc,KAAAhB,EAAAJ,EAAA,GAAAoB,EAAAd,EAAA,KAAAC,EAAA,EAAAU,EAAAC,EAAAhB,EAAAe,EAAAf,EAAAI,EAAA,IAAAc,EAAAG,IAAAnB,EAAAJ,EAAA,GAAAM,EAAA,GAAAJ,GAAAA,EAAAqB,KAAAjB,EAAA,GAAAN,EAAAM,EAAA,GAAAJ,EAAAe,EAAAf,EAAAqB,EAAAhB,EAAA,GAAA,CAAA,GAAAH,GAAAJ,EAAA,EAAA,OAAAmB,EAAA,MAAAH,GAAA,EAAAd,CAAA,CAAA,OAAA,SAAAE,EAAAW,EAAAQ,GAAA,GAAAT,EAAA,EAAA,MAAAU,UAAA,gCAAA,IAAAR,GAAA,IAAAD,GAAAK,EAAAL,EAAAQ,GAAAhB,EAAAQ,EAAAL,EAAAa,GAAAxB,EAAAQ,EAAA,EAAAT,EAAAY,KAAAM,GAAA,CAAAV,IAAAC,EAAAA,EAAA,GAAAA,EAAA,IAAAU,EAAAf,GAAA,GAAAkB,EAAAb,EAAAG,IAAAO,EAAAf,EAAAQ,EAAAO,EAAAC,EAAAR,GAAA,IAAA,GAAAI,EAAA,EAAAR,EAAA,CAAA,GAAAC,IAAAH,EAAA,QAAAL,EAAAO,EAAAF,GAAA,CAAA,KAAAL,EAAAA,EAAA0B,KAAAnB,EAAAI,IAAA,MAAAc,UAAA,oCAAA,IAAAzB,EAAA2B,KAAA,OAAA3B,EAAAW,EAAAX,EAAA4B,MAAApB,EAAA,IAAAA,EAAA,EAAA,MAAA,IAAAA,IAAAR,EAAAO,EAAA,SAAAP,EAAA0B,KAAAnB,GAAAC,EAAA,IAAAG,EAAAc,UAAA,oCAAApB,EAAA,YAAAG,EAAA,GAAAD,EAAAR,CAAA,MAAA,IAAAC,GAAAiB,EAAAC,EAAAf,EAAA,GAAAQ,EAAAV,EAAAyB,KAAAvB,EAAAe,MAAAE,EAAA,KAAA,CAAA,MAAApB,GAAAO,EAAAR,EAAAS,EAAA,EAAAG,EAAAX,CAAA,CAAA,QAAAe,EAAA,CAAA,CAAA,CAAA,MAAA,CAAAa,MAAA5B,EAAA2B,KAAAV,EAAA,CAAA,CAAA,CAAAhB,EAAAI,EAAAE,IAAA,GAAAI,CAAA,CAAA,IAAAS,EAAA,CAAA,EAAA,SAAAV,IAAA,CAAA,SAAAmB,IAAA,CAAA,SAAAC,IAAA,CAAA9B,EAAAY,OAAAmB,eAAA,IAAAvB,EAAA,GAAAL,GAAAH,EAAAA,EAAA,GAAAG,QAAAW,oBAAAd,EAAA,CAAA,EAAAG,EAAA,WAAA,OAAA6B,IAAA,GAAAhC,GAAAW,EAAAmB,EAAArB,UAAAC,EAAAD,UAAAG,OAAAC,OAAAL,GAAA,SAAAO,EAAAhB,GAAA,OAAAa,OAAAqB,eAAArB,OAAAqB,eAAAlC,EAAA+B,IAAA/B,EAAAmC,UAAAJ,EAAAhB,oBAAAf,EAAAM,EAAA,sBAAAN,EAAAU,UAAAG,OAAAC,OAAAF,GAAAZ,CAAA,CAAA,OAAA8B,EAAApB,UAAAqB,EAAAhB,oBAAAH,EAAA,cAAAmB,GAAAhB,oBAAAgB,EAAA,cAAAD,GAAAA,EAAAM,YAAA,oBAAArB,oBAAAgB,EAAAzB,EAAA,qBAAAS,oBAAAH,GAAAG,oBAAAH,EAAAN,EAAA,aAAAS,oBAAAH,EAAAR,EAAA,WAAA,OAAA6B,IAAA,GAAAlB,oBAAAH,EAAA,WAAA,WAAA,MAAA,oBAAA,IAAAb,aAAA,WAAA,MAAA,CAAAsC,EAAA7B,EAAA8B,EAAAtB,EAAA,IAAA,CAAA,SAAAD,oBAAAf,EAAAE,EAAAE,EAAAH,GAAA,IAAAO,EAAAK,OAAA0B,eAAA,IAAA/B,EAAA,CAAA,EAAA,GAAA,CAAA,EAAA,CAAA,MAAAR,GAAAQ,EAAA,CAAA,CAAAO,oBAAA,SAAAf,EAAAE,EAAAE,EAAAH,GAAA,SAAAK,EAAAJ,EAAAE,GAAAW,oBAAAf,EAAAE,EAAA,SAAAF,GAAA,OAAAiC,KAAAO,QAAAtC,EAAAE,EAAAJ,EAAA,EAAA,CAAAE,EAAAM,EAAAA,EAAAR,EAAAE,EAAA,CAAA2B,MAAAzB,EAAAqC,YAAAxC,EAAAyC,cAAAzC,EAAA0C,UAAA1C,IAAAD,EAAAE,GAAAE,GAAAE,EAAA,OAAA,GAAAA,EAAA,QAAA,GAAAA,EAAA,SAAA,GAAA,EAAAS,oBAAAf,EAAAE,EAAAE,EAAAH,EAAA,CAAA,SAAA2C,mBAAAxC,EAAAH,EAAAD,EAAAE,EAAAI,EAAAe,EAAAZ,GAAA,IAAA,IAAAD,EAAAJ,EAAAiB,GAAAZ,GAAAG,EAAAJ,EAAAqB,KAAA,CAAA,MAAAzB,GAAA,YAAAJ,EAAAI,EAAA,CAAAI,EAAAoB,KAAA3B,EAAAW,GAAAiC,QAAAC,QAAAlC,GAAAmC,KAAA7C,EAAAI,EAAA,CAAA,SAAA0C,kBAAA5C,GAAA,OAAA,WAAA,IAAAH,EAAAgC,KAAAjC,EAAAiD,UAAA,OAAA,IAAAJ,QAAA,SAAA3C,EAAAI,GAAA,IAAAe,EAAAjB,EAAA8C,MAAAjD,EAAAD,GAAA,SAAAmD,EAAA/C,GAAAwC,mBAAAvB,EAAAnB,EAAAI,EAAA6C,EAAAC,EAAA,OAAAhD,EAAA,CAAA,SAAAgD,EAAAhD,GAAAwC,mBAAAvB,EAAAnB,EAAAI,EAAA6C,EAAAC,EAAA,QAAAhD,EAAA,CAAA+C,OAAA,EAAA,EAAA,CAAA,CAAA,SAAAE,mBAAAnD,GAAA,OAAAoD,mBAAApD,IAAAqD,iBAAArD,IAAAsD,4BAAAtD,IAAAuD,oBAAA,CAAA,SAAAA,qBAAA,MAAA,IAAA/B,UAAA,uIAAA,CAAA,SAAA6B,iBAAArD,GAAA,GAAA,oBAAAC,QAAA,MAAAD,EAAAC,OAAAE,WAAA,MAAAH,EAAA,cAAA,OAAAwD,MAAAC,KAAAzD,EAAA,CAAA,SAAAoD,mBAAApD,GAAA,GAAAwD,MAAAE,QAAA1D,GAAA,OAAA2D,kBAAA3D,EAAA,CAAA,SAAA4D,yBAAA9D,EAAAC,GAAA,GAAA,MAAAD,EAAA,MAAA,CAAA,EAAA,IAAAM,EAAAJ,EAAAM,EAAAuD,8BAAA/D,EAAAC,GAAA,GAAAY,OAAAmD,sBAAA,CAAA,IAAA5D,EAAAS,OAAAmD,sBAAAhE,GAAA,IAAAE,EAAA,EAAAA,EAAAE,EAAAoB,OAAAtB,IAAAI,EAAAF,EAAAF,IAAA,IAAAD,EAAAgE,QAAA3D,IAAA,CAAA,EAAA4D,qBAAAvC,KAAA3B,EAAAM,KAAAE,EAAAF,GAAAN,EAAAM,GAAA,CAAA,OAAAE,CAAA,CAAA,SAAAuD,8BAAA7D,EAAAF,GAAA,GAAA,MAAAE,EAAA,MAAA,CAAA,EAAA,IAAAD,EAAA,CAAA,EAAA,IAAA,IAAAG,KAAAF,EAAA,GAAA,CAAA,EAAAiE,eAAAxC,KAAAzB,EAAAE,GAAA,CAAA,IAAA,IAAAJ,EAAAiE,QAAA7D,GAAA,SAAAH,EAAAG,GAAAF,EAAAE,EAAA,CAAA,OAAAH,CAAA,CAAA,SAAAmE,2BAAAlE,EAAAF,GAAA,IAAAC,EAAA,oBAAAE,QAAAD,EAAAC,OAAAE,WAAAH,EAAA,cAAA,IAAAD,EAAA,CAAA,GAAAyD,MAAAE,QAAA1D,KAAAD,EAAAuD,4BAAAtD,KAAAF,GAAAE,GAAA,iBAAAA,EAAAsB,OAAA,CAAAvB,IAAAC,EAAAD,GAAA,IAAAoE,EAAA,EAAAC,EAAA,WAAA,EAAA,MAAA,CAAAC,EAAAD,EAAAlE,EAAA,WAAA,OAAAiE,GAAAnE,EAAAsB,OAAA,CAAAI,MAAA,GAAA,CAAAA,MAAA,EAAAC,MAAA3B,EAAAmE,KAAA,EAAArE,EAAA,SAAAE,GAAA,MAAAA,CAAA,EAAAc,EAAAsD,EAAA,CAAA,MAAA,IAAA5C,UAAA,wIAAA,CAAA,IAAApB,EAAAe,GAAA,EAAAT,GAAA,EAAA,MAAA,CAAA2D,EAAA,WAAAtE,EAAAA,EAAA0B,KAAAzB,EAAA,EAAAE,EAAA,WAAA,IAAAF,EAAAD,EAAAuE,OAAA,OAAAnD,EAAAnB,EAAA0B,KAAA1B,CAAA,EAAAF,EAAA,SAAAE,GAAAU,GAAA,EAAAN,EAAAJ,CAAA,EAAAc,EAAA,WAAA,IAAAK,GAAA,MAAApB,EAAA,QAAAA,EAAA,QAAA,CAAA,QAAA,GAAAW,EAAA,MAAAN,CAAA,CAAA,EAAA,CAAA,SAAAmE,eAAAvE,EAAAF,GAAA,OAAA0E,gBAAAxE,IAAAyE,sBAAAzE,EAAAF,IAAAwD,4BAAAtD,EAAAF,IAAA4E,kBAAA,CAAA,SAAAA,mBAAA,MAAA,IAAAlD,UAAA,4IAAA,CAAA,SAAA8B,4BAAAtD,EAAAmB,GAAA,GAAAnB,EAAA,CAAA,GAAA,iBAAAA,EAAA,OAAA2D,kBAAA3D,EAAAmB,GAAA,IAAApB,EAAA,CAAA,EAAA4E,SAAAlD,KAAAzB,GAAA4E,MAAA,GAAA,GAAA,MAAA,WAAA7E,GAAAC,EAAA6E,cAAA9E,EAAAC,EAAA6E,YAAAC,MAAA,QAAA/E,GAAA,QAAAA,EAAAyD,MAAAC,KAAAzD,GAAA,cAAAD,GAAA,2CAAAgF,KAAAhF,GAAA4D,kBAAA3D,EAAAmB,QAAA,CAAA,CAAA,CAAA,SAAAwC,kBAAA3D,EAAAmB,IAAA,MAAAA,GAAAA,EAAAnB,EAAAsB,UAAAH,EAAAnB,EAAAsB,QAAA,IAAA,IAAAxB,EAAA,EAAAI,EAAAsD,MAAArC,GAAArB,EAAAqB,EAAArB,IAAAI,EAAAJ,GAAAE,EAAAF,GAAA,OAAAI,CAAA,CAAA,SAAAuE,sBAAAzE,EAAAuB,GAAA,IAAAxB,EAAA,MAAAC,EAAA,KAAA,oBAAAC,QAAAD,EAAAC,OAAAE,WAAAH,EAAA,cAAA,GAAA,MAAAD,EAAA,CAAA,IAAAD,EAAAI,EAAAI,EAAAI,EAAAS,EAAA,GAAAL,GAAA,EAAAV,GAAA,EAAA,IAAA,GAAAE,GAAAP,EAAAA,EAAA0B,KAAAzB,IAAAsE,KAAA,IAAA/C,EAAA,CAAA,GAAAZ,OAAAZ,KAAAA,EAAA,OAAAe,GAAA,CAAA,MAAA,OAAAA,GAAAhB,EAAAQ,EAAAmB,KAAA1B,IAAA2B,QAAAP,EAAA6D,KAAAlF,EAAA6B,OAAAR,EAAAG,SAAAC,GAAAT,GAAA,GAAA,CAAA,MAAAd,GAAAI,GAAA,EAAAF,EAAAF,CAAA,CAAA,QAAA,IAAA,IAAAc,GAAA,MAAAf,EAAA,SAAAW,EAAAX,EAAA,SAAAY,OAAAD,KAAAA,GAAA,MAAA,CAAA,QAAA,GAAAN,EAAA,MAAAF,CAAA,CAAA,CAAA,OAAAiB,CAAA,CAAA,CAAA,SAAAqD,gBAAAxE,GAAA,GAAAwD,MAAAE,QAAA1D,GAAA,OAAAA,CAAA,CAAA,SAAAiF,QAAA7E,GAAA,OAAA6E,QAAA,mBAAAhF,QAAA,iBAAAA,OAAAE,SAAA,SAAAC,GAAA,cAAAA,CAAA,EAAA,SAAAA,GAAA,OAAAA,GAAA,mBAAAH,QAAAG,EAAAyE,cAAA5E,QAAAG,IAAAH,OAAAO,UAAA,gBAAAJ,CAAA,EAAA6E,QAAA7E,EAAA,CADA8E,OAAOC,kBAAoB,WAGvB,IAAIC,EAAgB,CAEhBC,sBAAuB,kBACvBC,uBAAwB,IACxBC,mBAAoB,iBACpBC,mBAAoB,0BACpBC,wBAAyB,WACzBC,UAAW,MACXC,eAAgB,YAChBC,cAAe,YACfC,gBAAiB,cACjBC,UAAW,4CACXC,YAAa,gCACbC,eAAgB,UAChBC,iBAAkB,IAClBC,OAAQ,CACJC,oBAAqB,KACrBC,oBAAqB,KACrBC,mBAAoB,KACpBC,kBAAmB,KACnBC,mBAAoB,KACpBC,cAAe,KACfC,qBAAsB,KACtBC,wBAAyB,KACzBC,mBAAoB,yBACpBC,gBAAgB,EAChBC,gBAAgB,EAChBC,eAAe,EACfC,aAAc,KACdC,cAAe,KACfC,SAAU,IACVC,UAAW,KAEfC,gBAAe,g7KA4DfC,kBAAiB,oYAWrB,SAASC,EAAYC,GACjB,IAAKA,EAAK,MAAO,GACjB,IAAIC,EAAUD,EAAIE,OAClB,MAAI,gBAAgBzC,KAAKwC,IAAY,cAAcxC,KAAKwC,IAAY,oBAAoBxC,KAAKwC,GAClF,GAEJD,CACX,CAGA,SAASG,EAAmBC,GACxB,IAAIC,EAAOC,SAASC,cAAc,QAElC,OADAF,EAAKG,YAAcJ,EACZC,EAAKI,SAChB,CAeA,SAASC,EAAwBC,GAC7B,IAAIC,EAAchD,OAAOiD,aAd7B,SAAyCF,GACrC,IAAKA,GAA0B,IAAlBA,EAAKG,SACd,OAAO,EAGX,IAAIC,EAAW,yCACf,QAA4B,mBAAjBJ,EAAKK,UAA0BL,EAAKK,QAAQD,KAIlB,mBAAvBJ,EAAKM,iBAAkCN,EAAKM,cAAcF,EAC5E,EAISG,CAAgCP,IAAUC,GAAgBA,EAAYO,KAAwC,mBAA1BP,EAAYO,IAAIC,OAIzGR,EAAYO,IAAIC,MAAM,CAAEC,KAAMV,GAClC,CAEA,SAASW,EAAwBX,GAC7B,IAAKA,GAAoC,oBAArBY,iBAChB,OAAO,KAGX,IAAIC,EAAW,IAAID,iBAAiB,SAAUE,GAC1CA,EAAUC,QAAQ,SAAUC,GACxBA,EAASC,WAAWF,QAAQ,SAAUL,GAClCX,EAAwBW,EAC5B,EACJ,EACJ,GAOA,OALAG,EAASK,QAAQlB,EAAM,CACnBmB,WAAW,EACXC,SAAS,IAGNP,CACX,CAmBA,SAASQ,EAAmBC,GAAW,IAAAC,EAAAC,EAAAC,EAAAC,EAAAC,EAAAC,EAAAC,EAAAC,EAAAC,EAAAC,EAAAC,EACnC,IAAKX,GAAkC,WAArBtE,QAAOsE,GACrB,OAAO,KAGX,IAAMY,EAAaxJ,OAAOyJ,OAAO,CAAC,EAAGb,GAQrC,OAPAY,EAAWE,MAA4C,QAAvCb,EAAmB,QAAnBC,EAAGU,EAAWE,aAAK,IAAAZ,EAAAA,EAAIU,EAAWG,aAAK,IAAAd,EAAAA,EAAI,EAC3DW,EAAWzC,KAAyC,QAArCgC,EAAkB,QAAlBC,EAAGQ,EAAWzC,YAAI,IAAAiC,EAAAA,EAAIQ,EAAWI,YAAI,IAAAb,EAAAA,EAAI,KACxDS,EAAWK,MAA4C,QAAvCZ,EAAmB,QAAnBC,EAAGM,EAAWK,aAAK,IAAAX,EAAAA,EAAIM,EAAWM,aAAK,IAAAb,EAAAA,EAAI,KAC3DO,EAAWO,KAAOrD,EAA8C,QAAnCyC,EAAgB,QAAhBC,EAACI,EAAWO,YAAI,IAAAX,EAAAA,EAAII,EAAWQ,YAAI,IAAAb,EAAAA,EAAI,MACpEK,EAAWS,cAAoE,QAAvDZ,EAA2B,QAA3BC,EAAGE,EAAWS,qBAAa,IAAAX,EAAAA,EAAIE,EAAWU,qBAAa,IAAAb,EAAAA,EAAI,KACnFG,EAAWW,aAAqE,KAAhC,QAAvBZ,EAACC,EAAWW,mBAAW,IAAAZ,EAAAA,EAAIC,EAAWY,aAExDZ,CACX,CAEA,SAASa,EAA4BzB,GACjC,SAAKA,GAAkC,WAArBtE,QAAOsE,MAIc,iBAA5BA,EAAUqB,eAAwE,aAA1CrB,EAAUqB,cAAcK,iBAI7C,iBAAnB1B,EAAUmB,OAAqB,yCAAyC3F,KAAKwE,EAAUmB,OAKtG,CAEA,SAASQ,EAAoBC,GACzB,IAAKA,GAAoC,WAAtBlG,QAAOkG,GACtB,MAAO,CAAC,EAKZ,IAFA,IAAMhB,EAAa,CAAC,EAEpBiB,EAAA,EAAAC,EAA2B1K,OAAO2K,QAAQH,GAAWC,EAAAC,EAAA/J,OAAA8J,IAAE,CAAA,IAAAG,EAAlDC,EAAAjH,eAAA8G,EAAAD,GAAA,GAAOK,EAAGD,EAAA,GAAE7J,EAAK6J,EAAA,GAClBrB,EAAWsB,GAAgC,QAA5BF,EAAGjC,EAAmB3H,UAAM,IAAA4J,EAAAA,EAAI,CAAC,CACpD,CAEA,OAAOpB,CACX,CAEA,SAASuB,EAAiBnC,EAAWkC,GACjC,OAAOlC,EAAUiB,OAASjB,EAAU7B,MAAQ+D,CAChD,CA4FA,SAASE,EAA0BC,EAAST,GACxC,IAAMU,EAAoBX,EAAoBC,QAAAA,EAAcS,EAAQT,YAC9DW,EAA2C,iBAAvBF,EAAQE,WAC5BF,EAAQE,WACmB,iBAApBF,EAAQG,QACXH,EAAQG,QACR,GACJC,EAjGV,SAA8BD,EAASZ,GACnC,IAAIc,GAAoBF,GAAW,IAAIvE,OACjCqE,EAAoBX,EAAoBC,GACxCe,EAAmBvL,OAAO2K,QAAQO,GAExC,IAAKK,EAAiB5K,OAClB,MAAO,CAAEyK,QAASE,EAAkBE,UAAW,IAGnD,IAAMC,EAAYF,EAAiBG,OAAO,SAAAC,GAAA,IAAEb,EAAFlH,eAAA+H,EAAA,GAAK,GAAA,OAAML,EAAiBM,SAASd,EAAI,GAC7Ee,EAAgBN,EAAiBG,OAAO,SAAAI,GAAA,IAAAC,EAAAnI,eAAAkI,EAAA,GAAEhB,EAAGiB,EAAA,GAAO,OAAAA,EAAA,GAAY5B,cAAgBmB,EAAiBM,SAASd,EAAI,GAEpH,IAAKW,EAAU9K,SAAWkL,EAAclL,OACpC,MAAO,CAAEyK,QAASE,EAAkBE,UAAW,IAGnDC,EAAUO,KAAK,SAAAC,EAAAC,GAAA,IAAI1L,EAAJoD,eAAAqI,EAAA,GAAK,GAAME,EAANvI,eAAAsI,EAAA,GAAO,GAAA,OAAM1L,EAAEkJ,MAAQyC,EAAEzC,KAAK,GAClDmC,EAAcG,KAAK,SAAAI,EAAAC,GAAA,IAAI7L,EAAJoD,eAAAwI,EAAA,GAAK,GAAMD,EAANvI,eAAAyI,EAAA,GAAO,GAAA,OAAM7L,EAAEkJ,MAAQyC,EAAEzC,KAAK,GAEtD,IAGoC4C,EAH9Bd,EAAY,GACde,EAAe,EAAEC,EAAAjJ,2BAEMkI,GAAS,IAApC,IAAAe,EAAA9I,MAAA4I,EAAAE,EAAAjN,KAAAwB,MAAsC,CAAA,IAAA0L,EAAA7I,eAAA0I,EAAAtL,MAAA,GAA1B8J,EAAG2B,EAAA,GAAEzL,EAAKyL,EAAA,GACZC,EAAW,UAAAC,OAAaJ,EAAY,KAAAI,OAAI3L,EAAM0I,OAAS6C,EAAY,MACzEjB,EAAmBA,EAAiBsB,WAAW9B,EAAK4B,GACpDlB,EAAUnH,KAAK,CACXwI,aAAc/B,EACdyB,aAAcA,EACdO,MAAO/B,EAAiB/J,EAAO8J,GAC/Bf,KAAM/I,EAAM+I,MAAQ,KACpBgD,WAAY1C,EAA4BrJ,GACxC0L,YAAaA,IAGjBH,GACJ,CAAC,CAAA,MAAAS,GAAAR,EAAArN,EAAA6N,EAAA,CAAA,QAAAR,EAAArM,GAAA,CAED,IAAA,IAAA8M,EAAA,EAAAC,EAAuB1B,EAASyB,EAAAC,EAAAvM,OAAAsM,IAAE,CAA7B,IAAME,EAAQD,EAAAD,GACf3B,EAAmBA,EAAiBsB,WAAWO,EAAST,YAAW,QAAAC,OAAUQ,EAASZ,aAAY,UACtG,CAEAjB,EAAmBA,EAAiBsB,WAAW,cAAe,2BAG9D,IACwCQ,EADxCC,EAAA9J,2BAC2BsI,GAAa,IAAxC,IAAAwB,EAAA3J,MAAA0J,EAAAC,EAAA9N,KAAAwB,MAA0C,CAAA,IAAAuM,EAAA1J,eAAAwJ,EAAApM,MAAA,GAA9B8J,EAAGwC,EAAA,GAAEtM,EAAKsM,EAAA,GAClB9B,EAAUnH,KAAK,CACXwI,aAAc/B,EACdyB,aAAcA,EACdO,MAAO/B,EAAiB/J,EAAO8J,GAC/Bf,KAAM/I,EAAM+I,MAAQ,KACpBgD,YAAY,EACZL,YAAa,OAGjBH,GACJ,CAAC,CAAA,MAAAS,GAAAK,EAAAlO,EAAA6N,EAAA,CAAA,QAAAK,EAAAlN,GAAA,CAED,MAAO,CACHiL,QAASE,EACTE,UAAWA,EAAU+B,IAAI,SAAAC,GAA2B,OAAbA,EAAXd,YAAwBzJ,yBAAAuK,EAAAvO,UAAe,GAE3E,CAmC4BwO,CAAqBtC,EAAYD,GAUzD,OARAD,EAAQE,WAAaA,EACrBF,EAAQG,QAAUD,EAClBF,EAAQyC,eAAiBrC,EAAgBD,QACzCH,EAAQT,WAAaU,EACrBD,EAAQ0C,mBAAqBtC,EAAgBG,UAC7CP,EAAQ2C,YAxCZ,SAA0BxC,EAASI,GAC/B,IAAIoC,GAAexC,GAAW,IAAIvE,OAElC,IAAK+G,IAAgB/K,MAAME,QAAQyI,IAAmC,IAArBA,EAAU7K,OACvD,OAAOiN,EACV,IAE+BC,EAF/BC,EAAAvK,2BAEsBiI,GAAS,IAAhC,IAAAsC,EAAApK,MAAAmK,EAAAC,EAAAvO,KAAAwB,MAAkC,CAAA,IAAvBoM,EAAQU,EAAA7M,MACf4M,EAAcA,EAAYhB,WAAWO,EAASN,aAAY,IAAAF,OAAMQ,EAASZ,aAAY,KACzF,CAAC,CAAA,MAAAS,GAAAc,EAAA3O,EAAA6N,EAAA,CAAA,QAAAc,EAAA3N,GAAA,CAEDyN,GAAe,oBAAoB,IAEHG,EAFGC,EAAAzK,2BAEZiI,GAAS,IAAhC,IAAAwC,EAAAtK,MAAAqK,EAAAC,EAAAzO,KAAAwB,MAAkC,CAAA,IAAvBoM,EAAQY,EAAA/M,MACf4M,GAAW,GAAAjB,OAAOQ,EAASZ,aAAY,MAAAI,OAAKQ,EAASL,OAEjDK,EAASpD,OACT6D,GAAW,MAAAjB,OAAUQ,EAASpD,OAGlC6D,GAAe,IACnB,CAAC,CAAA,MAAAZ,GAAAgB,EAAA7O,EAAA6N,EAAA,CAAA,QAAAgB,EAAA7N,GAAA,CAED,OAAOyN,EAAYK,SACvB,CAgB0BC,CAAiB/C,EAAYE,EAAgBG,WACnEP,EAAQkD,YAAcC,EAAqB/C,EAAgBD,QAASH,GAE7DA,CACX,CAEA,IAAMoD,EAAW,IAAIC,OAAOC,SAG5BF,EAAStE,KAAO,SAAUyE,GACtB,IAAIC,EAAO/H,EAAY8H,EAAKC,MAC5B,OAAKA,EACL,YAAA9B,OAAmB8B,EAAI,gDAAA9B,OAA+C6B,EAAKzH,KAAI,QAD7DyH,EAAKzH,MAAQ,EAEnC,EAGAsH,EAASK,KAAO,SAAUF,GACtB,IAAIE,EAAOF,EAAKzH,MAAQ,GACpB4H,GAAQH,EAAKG,MAAQ,IAAI9H,OACzB+H,EAAcF,EAElB,GAAoB,oBAATG,KACP,GAAIF,GAAQE,KAAKC,YAAYH,GACzB,IACIC,EAAcC,KAAKE,UAAUL,EAAM,CAAEM,SAAUL,IAAQ3N,KAC3D,CAAE,MAAOiO,GAAK,MAEd,IACIL,EAAcC,KAAKK,cAAcR,GAAM1N,KAC3C,CAAE,MAAOiO,GAAK,MAGlBL,EAAc9H,EAAmB4H,GAGrC,IAAIS,EAAcR,EAAO7H,EAAmB6H,GAAQ,OACpD,MAAA,sHAAAhC,OAA6HwC,EAAW,mJAAAxC,OAAkJgC,EAAO,aAAeA,EAAO,GAAE,MAAAhC,OAAKiC,EAAW,sBAC7U,EAIAP,EAASe,MAAQ,SAAUZ,GACvB,IAAMa,EAAM3I,EAAY8H,EAAKC,MAC7B,IAAKY,EAAK,MAAO,GACjB,IAAMC,EAAMd,EAAKzH,MAAQtC,EAAcC,sBACjC6K,EAAW9K,EAAcE,uBAC/B,MAAA,8DAAAgI,OACY0C,EAAG,WAAA1C,OAAU2C,EAAG,8CAAA3C,OAA6C4C,EAAQ,4EAAA5C,OAElE0C,EAAG,gCAAA1C,OAA+B2C,EAAG,aAAA3C,OAAYlI,EAAcG,mBAAkB,oKAKpG,EAGA,IAAI4K,EAAe,EAGfC,EAAiB,GA0HrB,SAASC,EAAsBzE,GAC3B,GAAKA,GAAYA,EAAQwE,gBAAmBxE,EAAQwE,eAAe9O,OAAnE,CAKA,IAAMgP,EAAMnN,mBAAOyI,EAAQwE,gBAC3BxE,EAAQwE,eAAiB,GAIzBG,sBAAsB,WAAM,IACFC,EADEC,EAAAvM,2BACRoM,GAAM,IAAtB,IAAAG,EAAApM,MAAAmM,EAAAC,EAAAvQ,KAAAwB,MAAwB,CAAA,IAAbnB,EAACiQ,EAAA7O,MACR+O,EAAoBnQ,EAAEoQ,QAASpQ,EAAEqQ,OACrC,CAAC,CAAA,MAAAjD,GAAA8C,EAAA3Q,EAAA6N,EAAA,CAAA,QAAA8C,EAAA3P,GAAA,CACL,EAZA,CAaJ,CAEA,SAAS4P,EAAoBC,EAASC,GAClC,IAAMC,EAASjJ,SAASkJ,eAAeH,GACvC,IAAKE,EACD,OAAO,EAGX,GAAqB,oBAAVE,MAEP,OADAC,QAAQC,KAAK,mMACN,EAOX,GAA4B,OAAxBJ,EAAOK,aAEP,OADAhM,OAAOiM,eAAeR,GAAWC,GAC1B,EAGX,IAAI,IAAAQ,EAAAC,EAAAC,EACIT,EAAOU,gBACPV,EAAOU,eAAeC,UAG1B,IAAMC,EAAwB,iBAAXb,EAAsBc,KAAKC,MAAMf,GAAUA,EAQ9D,OAPW,QAAXQ,EAAAK,EAAIG,eAAO,IAAAR,IAAXK,EAAIG,QAAY,CAAC,GACjBH,EAAIG,QAAQC,YAAa,EACzBJ,EAAIG,QAAQE,qBAAsB,EACX,QAAvBR,GAAAD,EAAAI,EAAIG,SAAQG,mBAAW,IAAAT,IAAvBD,EAAYU,YAAgB,EAAI,GAEhClB,EAAOU,eAAiB,IAAIR,MAAMF,EAAQY,UACnCvM,OAAOiM,eAAeR,IACtB,CACX,CAAE,MAAO7Q,GAEL,OADAkR,QAAQgB,MAAM,wBAAyBlS,IAChC,CACX,CACJ,CAyBA,SAASiP,EAAqBhD,EAASH,GACnCwE,EAAiB,GACjB,IAAM6B,EAAOhD,OAAO0C,MAAM5F,EAAS,CAAEiD,SAAAA,IAErC,OADApD,EAAQwE,eAAiBA,EAAe9O,OAAS,EAAC6B,mBAAOiN,GAAkB,GACpE8B,UAAUC,SAASF,EAAM,CAAEG,SAAU,CAAC,UAAWC,SAAU,CAAC,WACvE,CAEA,SAASC,EAAcC,GACnB,OAAKA,GAA4B,WAAlBtN,QAAOsN,GAIf5R,OAAO6R,YACV7R,OAAO2K,QAAQiH,GAAQlG,OAAO,SAAAoG,GAAS,YAAgBC,IAAzBnO,eAAAkO,EAAA,GAAS,EAAyB,IAJzD,CAAC,CAMhB,CArNAvN,OAAOiM,eAAiBjM,OAAOiM,gBAAkB,CAAC,EAelDlC,OAAO0D,IAAI,CACPC,WAAY,CAAC,CACT9N,KAAM,QACN+N,MAAO,QACPC,MAAK,SAAC9C,GACF,IAAM+C,EAAM/C,EAAIjM,QAAQ,WACxB,OAAOgP,GAAO,EAAIA,OAAML,CAC5B,EACAM,UAAS,SAAChD,GACN,IAAMiD,EAuBlB,SAA+BvL,GAC3B,IAAMwL,EAAQ,UACRJ,EAAQpL,EAAK3D,QAAQmP,GAC3B,GAAIJ,EAAQ,EACR,OAAO,KAIX,IAAMK,EAAYL,EAAQI,EAAM5R,OAC5BhB,EAAI6S,EACR,KAAO7S,EAAIoH,EAAKpG,SAAuB,MAAZoG,EAAKpH,IAA0B,OAAZoH,EAAKpH,IAA2B,OAAZoH,EAAKpH,IAA2B,OAAZoH,EAAKpH,KACvFA,IAGJ,GAAIA,GAAKoH,EAAKpG,QAAsB,MAAZoG,EAAKpH,GACzB,OAAO,KAOX,IAJA,IAAI8S,EAAQ,EACRC,GAAW,EACXC,GAAS,EAENhT,EAAIoH,EAAKpG,OAAQhB,IAAK,CACzB,IAAMiT,EAAK7L,EAAKpH,GAEhB,GAAI+S,EAAJ,CACI,GAAIC,EAAQ,CACRA,GAAS,EACT,QACJ,CACA,GAAW,OAAPC,EAAa,CACbD,GAAS,EACT,QACJ,CACW,MAAPC,IACAF,GAAW,EAGnB,MAEA,GAAW,MAAPE,GAKJ,GAAW,MAAPA,EACAH,SACG,GAAW,MAAPG,GAEO,MADdH,EACiB,CACb,IAAMI,EAAUlT,EAEVmT,EAAoB/L,EAAK3D,QAAQ,IAAKyP,EAAU,GACtD,OAAIC,EAAoB,EACb,KAIJ,CACHC,WAAYZ,EACZa,SAAUF,EAAoB,EAC9BG,KAJSlM,EAAKmM,UAAUV,EAAWK,EAAU,GAAGhM,OAMxD,OAtBA6L,GAAW,CAwBnB,CAEA,OAAO,IACX,CA3F8BS,CAAsB9D,GACxC,GAAKiD,GAAsC,IAAzBA,EAAUS,WAA5B,CAIA,IAAM/C,EAAO,cAAArD,SAAmB6C,GAEhC,MAAO,CACH4D,KAAM,QACNC,IAAKhE,EAAI6D,UAAU,EAAGZ,EAAUU,UAChChD,QAASA,EACTiD,KAAMX,EAAUW,KARpB,CAUJ,EACA5E,SAAQ,SAACkE,GAGL,OAFA9C,EAAepL,KAAK,CAAE2L,QAASuC,EAAMvC,QAASC,OAAQsC,EAAMU,OAC5D1O,OAAOiM,eAAe+B,EAAMvC,SAAWuC,EAAMU,KAtChCjD,EAuCUuC,EAAMvC,QAtC9B,8GAAA,eAAArD,OACcqD,EAAO,eADrB,2BAGmB,oGAAArD,OACgFqD,EAAO,aAAArD,OAAYlI,EAAcI,mBAAkB,MAAI,wCAAA8H,OACnHlI,EAAcK,yBALrD,kBADX,IAAyBkL,CAwCjB,MAwIRzL,OAAO+O,oBAAsB,WACzB,GAAqB,oBAAVlD,MAAX,CAIA,IAAMmD,EAAUhP,OAAOiM,eAClB+C,GAIL3D,sBAAsB,WAClB,IAAA,IAAA4D,EAAA,EAAAC,EAAsBzT,OAAO0T,KAAKH,GAAQC,EAAAC,EAAA9S,OAAA6S,IAAE,CAAvC,IAAMxD,EAAOyD,EAAAD,GACdzD,EAAoBC,EAASuD,EAAQvD,GACzC,CACJ,EAXA,CAYJ,EA+BA,IAAM2D,EAAa,SAACC,GAChB,IAAMC,EAA2BlC,EAAciC,GACzCE,EAAyBnC,EAAckC,EAAyBtO,QAChE0K,EAASjQ,OAAOyJ,OAAO,CAAC,EAAGhF,EAAeoP,GAChD5D,EAAO1K,OAASvF,OAAOyJ,OAAO,CAAC,EAAGhF,EAAcc,QAAU,CAAC,EAAGuO,GAC9D7D,EAAOxJ,kBAdX,SAAkCsN,EAAU/O,GACxC,IAAK+O,EACD,OAAOA,EAGX,IAAMC,EAAwBlN,EAAmB9B,GAAkB,aACnE,OAAO+O,EAASE,QAAQ,gCAAiCD,EAC7D,CAO+BE,CAAyBjE,EAAOxJ,kBAAmBwJ,EAAOjL,gBACrF,IAAMmP,KAAqBL,EAAuBtO,sBAAuBsO,EAAuBrO,qBAC1F2O,EAAiB7P,OAAO8P,0BAA4B,KAI1D,GAFA5P,EAAgBwL,EAEXA,EAAOqE,cAKZ,GAAKrE,EAAOsE,mBAKZ,GAAKtE,EAAOuE,6BAKZ,GAAKvE,EAAOwE,qBAAZ,CAKA,GAAKxE,EAAOyE,0BAAZ,CAKA,IAAMC,EAAgB,CAClBnG,KAAI,WACA,MAAO,CACHoG,aAAc,KACdC,cAAe,KACfC,cAAe,KACfpI,YAAa,KACbqI,kBAAkB,EAClBC,sBAAsB,EACtBC,aAAa,EACbC,kBAAkB,EAClBC,YAAY,EACZC,OAAQ,KACRC,SAAU,GACVC,cAAe,GACfC,OAAQ,GACRC,UAAWvF,EAAOwF,mBAAqB,GACvCC,aAAa,EACbC,4BAA4B,EAC5BC,uBAAwB,KACxBC,aAAc,GACdC,YAAY,EACZC,YAAa,KACbC,iBAAkB/F,EAAO+F,eACzBjR,UAAWkL,EAAOlL,UAClBC,eAAgBiL,EAAOjL,eACvBC,cAAegL,EAAOhL,cACtBC,gBAAiB+K,EAAO/K,gBACxBC,UAAW8K,EAAO9K,UAClBC,YAAa6K,EAAO7K,YACpB6Q,aAAa,EACbC,cAAe,KACfC,mBAAoB,GACpBC,UAAW,KACXC,oBAAyC,eAApBpG,EAAOqG,UAAiD,iBAApBrG,EAAOqG,SAChEC,oBAAyC,iBAApBtG,EAAOqG,YAAiCrG,EAAOsG,oBACpEC,aAAcvG,EAAOuG,cAAgB,KACrCC,YAAa,GACbC,eAAgB,GAChBC,gBAAgB,EAChBC,oBAAqB,KACrBC,gBAAiB,KACjBC,UAAW,KACXC,wBAAyB,EACzBC,cAAe,CAAC,EAChBC,cAAe,WAAaC,KAAKC,SAASnT,SAAS,IAAIC,MAAM,GAC7DmT,qBAAsBnH,EAAOmH,mBAC7BC,wBAA6C,iBAApBpH,EAAOqG,SAChCgB,mBAAoB,KACpBC,oBAAoB,EACpBC,0BAA2B,CAAC,EAC5BC,sBAAuB,KACvBC,uBAAwB,KACxBC,uBAAwB,KACxBC,wBAAyB,KACzBC,oBAAqB,EACrBC,mBAAoB,KACpBC,iBAAkB,KAE1B,EACAC,SAAU,CACNC,mBAAkB,WACd,IAAK,IAAItY,EAAIyB,KAAKiU,SAAS1U,OAAS,EAAGhB,GAAK,EAAGA,IAC3C,GAA8B,cAA1ByB,KAAKiU,SAAS1V,GAAGuY,KACjB,OAAOvY,EAGf,OAAQ,CACZ,GAEJwY,QAAS,CACLC,mBAAkB,WACdhX,KAAK8T,kBAAmB,CAC5B,EACAmD,eAAc,SAAClZ,GACX,GAAK8Q,EAAOqI,wBAAZ,CACAnZ,EAAEoZ,iBACFpZ,EAAEqZ,kBACFpX,KAAK0U,YAAa,EAClB,IAAI2C,EAAYrX,KAAKwT,aAAexT,KAAKwT,aAAa8D,QAAQ,0CAA4C,KACtGD,GAAWA,EAAUE,UAAUC,IAAI,oBALF,CAMzC,EACAC,gBAAe,SAAC1Z,GACZ,GAAK8Q,EAAOqI,wBAAZ,CACAnZ,EAAEoZ,iBACFpZ,EAAEqZ,kBACFpX,KAAK0U,YAAa,EAClB,IAAI2C,EAAYrX,KAAKwT,aAAexT,KAAKwT,aAAa8D,QAAQ,0CAA4C,KACtGD,GAAWA,EAAUE,UAAUG,OAAO,oBALL,CAMzC,EACAC,WAAU,SAAC5Z,GACP,GAAK8Q,EAAOqI,wBAAZ,CACAnZ,EAAEoZ,iBACFpZ,EAAEqZ,kBACFpX,KAAK0U,YAAa,EAClB,IAAI2C,EAAYrX,KAAKwT,aAAexT,KAAKwT,aAAa8D,QAAQ,0CAA4C,KACtGD,GAAWA,EAAUE,UAAUG,OAAO,qBACtC3Z,EAAE6Z,cAAgB7Z,EAAE6Z,aAAaC,OAAS9Z,EAAE6Z,aAAaC,MAAMtY,OAAS,GACxES,KAAK8X,YAAYrW,MAAMC,KAAK3D,EAAE6Z,aAAaC,OAPV,CASzC,EACAE,iBAAgB,WACZ,GAAKlJ,EAAOqI,0BAA2BlX,KAAKuU,2BAA5C,CACA,IAAIyD,EAAYnS,SAASkJ,eAAe,qBACpCiJ,GAAWA,EAAUC,OAF+C,CAG5E,EACAC,sBAAqB,SAACna,GAClB,IAAI8Z,EAAQ9Z,EAAEoa,OAAON,MAAQpW,MAAMC,KAAK3D,EAAEoa,OAAON,OAAS,GACtDA,GAASA,EAAMtY,OAAS,GACxBS,KAAK8X,YAAYD,GAErB9Z,EAAEoa,OAAOvY,MAAQ,EACrB,EACAwY,uBAAsB,SAACC,GACnB,IAAIC,EAAOtY,KAEPuY,GADoBvY,KAAKwU,wBAA0B5T,QAAQC,WAC1B,MAC1B,WAAc,GACpBC,KAAIC,kBAAAjD,eAAAuC,EAAC,SAAAmY,IAAA,OAAA1a,eAAAsC,EAAA,SAAAqY,GAAA,cAAAA,EAAAzZ,EAAAyZ,EAAAta,GAAA,KAAA,EACqC,OAAvCma,EAAK/D,4BAA6B,EAAKkE,EAAAzZ,EAAA,EAAAyZ,EAAAta,EAAA,EAEtBka,IAAW,KAAA,EAAA,OAAAI,EAAArZ,EAAA,EAAAqZ,EAAAtZ,GAAA,KAAA,EAEgB,OAFhBsZ,EAAAzZ,EAAA,EAExBsZ,EAAK/D,4BAA6B,EAAMkE,EAAA1Z,EAAA,GAAA,KAAA,EAAA,OAAA0Z,EAAArZ,EAAA,GAAA,EAAAoZ,EAAA,KAAA,CAAA,CAAA,EAAA,CAAA,EAAA,IAAA,KAUpD,OANAxY,KAAKwU,uBAAyB+D,EAAa,QAAS,WAC5CD,EAAK9D,yBAA2B+D,IAChCD,EAAK9D,uBAAyB,KAEtC,GAEOxU,KAAKwU,sBAChB,EACMsD,YAAW,SAACD,GAAO,IAAAa,EAAA1Y,KAAA,OAAAe,kBAAAjD,eAAAuC,EAAA,SAAAsY,IAAA,IAAAC,EAAA,OAAA9a,eAAAsC,EAAA,SAAAyY,GAAA,cAAAA,EAAA1a,GAAA,KAAA,EAAA,GAChB0Q,EAAOiK,kBAAiB,CAAAD,EAAA1a,EAAA,EAAA,KAAA,CAAA,OAAA0a,EAAAzZ,EAAA,GAAA,KAAA,EAEqD,GACrD,KADzBwZ,EAAgBnX,MAAME,QAAQkW,GAASA,EAAMhV,QAAUpB,MAAMC,KAAKmW,GAAS,KAC7DtY,OAAY,CAAAsZ,EAAA1a,EAAA,EAAA,KAAA,CAAA,OAAA0a,EAAAzZ,EAAA,GAAA,KAAA,EAAA,OAAAyZ,EAAAzZ,EAAA,EAEvBsZ,EAAKN,uBAAsBrX,kBAAAjD,eAAAuC,EAAC,SAAA0Y,IAAA,IAAAC,EAAAC,EAAAC,EAAA3a,EAAA4a,EAAAC,EAAAC,EAAAC,EAAAC,EAAAC,EAAA,OAAA1b,eAAAsC,EAAA,SAAAqZ,GAAA,cAAAA,EAAAza,EAAAya,EAAAtb,GAAA,KAAA,EAEI,GAD/B6a,EAAYN,EAAKgB,eACjBT,EAAYP,EAAKiB,eAEhBX,EAAS,CAAAS,EAAAtb,EAAA,EAAA,KAAA,CAAA,OAAAsb,EAAAza,EAAA,EAAAya,EAAAtb,EAAA,EAEYua,EAAKkB,0BAA0BX,GAAU,KAAA,EAA3DD,EAASS,EAAAta,EAAAsa,EAAAtb,EAAA,EAAA,MAAA,KAAA,EAIgB,OAJhBsb,EAAAza,EAAA,EAAAua,EAAAE,EAAAta,EAET8P,QAAQgB,MAAM,uDAAsDsJ,GACpEb,EAAKjE,aAAe,CAAC,CAAEoF,SAAU,GAAI5J,MAAO,oDAC5CyI,EAAKoB,oBAAoBL,EAAAra,EAAA,GAAA,KAAA,EAAA,GAK5B4Z,EAAS,CAAAS,EAAAtb,EAAA,EAAA,KAAA,CAGe,OAFzB8Q,QAAQC,KAAK,yDACbwJ,EAAKjE,aAAe,CAAC,CAAEoF,SAAU,GAAI5J,MAAO,oDAC5CyI,EAAKoB,oBAAoBL,EAAAra,EAAA,GAAA,KAAA,EAUzB,IANJsZ,EAAKpE,aAAc,EACnBoE,EAAKjE,aAAe,GACpBiE,EAAKoB,oBAAoBL,EAAAza,EAAA,GAEjBka,EAAW,IAAIa,UACVC,OAAO,YAAahB,GACpBza,EAAI,EAAGA,EAAIqa,EAAcrZ,OAAQhB,IACtC2a,EAASc,OAAO,QAASpB,EAAcra,IAC1C,OAAAkb,EAAAtb,EAAA,EAEoB8b,MAAMpL,EAAOiK,kBAAmB,CACjDoB,OAAQ,OACRC,KAAMjB,IACR,KAAA,EAHU,IAARC,EAAQM,EAAAta,GAKEib,GAAE,CAAAX,EAAAtb,EAAA,EAAA,KAAA,CAAA,OAAAsb,EAAAtb,EAAA,EACUgb,EAASxT,OAAM,KAAA,EAGsB,OAHvDyT,EAASK,EAAAta,EACTka,EAAcX,EAAK2B,4BAA4BjB,EAAW,oCAC9DnK,QAAQgB,MAAM,iBAAkBmJ,GAChCV,EAAKjE,aAAe,CAAC,CAAEoF,SAAU,GAAI5J,MAAOoJ,IAAeI,EAAAra,EAAA,GAAA,KAAA,EAAA,OAAAqa,EAAAtb,EAAA,GAI5Cgb,EAAStH,OAAM,KAAA,IAA9ByH,EAAMG,EAAAta,GAEC6Z,WAAaM,EAAON,YAAcN,EAAKgB,gBAC9ChB,EAAK4B,kBAAkBhB,EAAON,WAG9BvX,MAAME,QAAQ2X,EAAOlF,WACrBsE,EAAKtE,UAAYkF,EAAOlF,UACjBkF,EAAOiB,UAAYjB,EAAOiB,SAAShb,OAAS,IACnDmZ,EAAKtE,UAAYsE,EAAKtE,UAAU7I,OAAO+N,EAAOiB,WAG9CjB,EAAOkB,QAAUlB,EAAOkB,OAAOjb,OAAS,IACxCmZ,EAAKjE,aAAe6E,EAAOkB,QAC9Bf,EAAAtb,EAAA,GAAA,MAAA,KAAA,GAAAsb,EAAAza,EAAA,GAAAwa,EAAAC,EAAAta,EAED8P,QAAQgB,MAAM,gBAAeuJ,GAC7Bd,EAAKjE,aAAe,CAAC,CAAEoF,SAAU,GAAI5J,MAAO,qCAExCyI,EAAKgB,gBACLhB,EAAK+B,uBACR,KAAA,GAGwB,OAHxBhB,EAAAza,EAAA,GAED0Z,EAAKpE,aAAc,EACnBoE,EAAKoB,oBAAoBL,EAAA1a,EAAA,IAAA,KAAA,GAAA,OAAA0a,EAAAra,EAAA,GAAA,EAAA2Z,EAAA,KAAA,CAAA,CAAA,EAAA,GAAA,GAAA,IAAA,CAAA,EAAA,IAAA,MAE/B,EAAAJ,EAAA,GA7EmB5X,EA8EzB,EACM2Z,eAAc,SAACC,GAAK,IAAAC,EAAA5a,KAAA,OAAAe,kBAAAjD,eAAAuC,EAAA,SAAAwa,IAAA,OAAA/c,eAAAsC,EAAA,SAAA0a,GAAA,cAAAA,EAAA3c,GAAA,KAAA,EAAA,GACjB0Q,EAAOkM,kBAAiB,CAAAD,EAAA3c,EAAA,EAAA,KAAA,CAAA,OAAA2c,EAAA1b,EAAA,GAAA,KAAA,EAAA,OAAA0b,EAAA1b,EAAA,EAEtBwb,EAAKxC,uBAAsBrX,kBAAAjD,eAAAuC,EAAC,SAAA2a,IAAA,IAAAhC,EAAAG,EAAAG,EAAAtI,EAAAoI,EAAA6B,EAAAC,EAAA,OAAApd,eAAAsC,EAAA,SAAA+a,GAAA,cAAAA,EAAAnc,EAAAmc,EAAAhd,GAAA,KAAA,EAEQ,OAFRgd,EAAAnc,EAAA,EAEvBga,EAAY4B,EAAKlB,eAAcyB,EAAAhd,EAAA,EACd8b,MAAMpL,EAAOkM,kBAAmB,CACjDb,OAAQ,OACRkB,QAAS,CAAE,eAAgB,oBAC3BjB,KAAMxK,KAAK0L,UAAU,CAAEC,OAAQtC,EAAWuC,WAAYZ,EAAIY,eAC5D,KAAA,EAJU,KAARpC,EAAQgC,EAAAhc,GAMCib,GAAE,CAAAe,EAAAhd,EAAA,EAAA,KAAA,CAAA,OAAAgd,EAAAhd,EAAA,EACQgb,EAAStH,OAAM,KAAA,EAA9ByH,EAAM6B,EAAAhc,EAENsC,MAAME,QAAQ2X,EAAOlF,WACrBwG,EAAKxG,UAAYkF,EAAOlF,WAEpBpD,EAAM4J,EAAKxG,UAAUpS,QAAQ2Y,KACtB,GACPC,EAAKxG,UAAUoH,OAAOxK,EAAK,GAElCmK,EAAAhd,EAAA,EAAA,MAAA,KAAA,EAAA,OAAAgd,EAAAhd,EAAA,EAEqBgb,EAASxT,OAAM,KAAA,EAAjCyT,EAAS+B,EAAAhc,EACT8b,EAAcL,EAAKP,4BAA4BjB,EAAW,gDAC9DnK,QAAQgB,MAAM,6BAA8BkJ,EAASsC,OAAQrC,GAC7DwB,EAAKnG,aAAe,CAAC,CAAEoF,SAAUc,EAAId,UAAY,GAAI5J,MAAOgL,IACxDjC,GACA4B,EAAKH,uBAETG,EAAKd,oBAAoB,KAAA,EAAAqB,EAAAhd,EAAA,EAAA,MAAA,KAAA,EAAAgd,EAAAnc,EAAA,EAAAkc,EAAAC,EAAAhc,EAG7B8P,QAAQgB,MAAM,yBAAwBiL,GACtCN,EAAKnG,aAAe,CAAC,CAAEoF,SAAUc,EAAId,UAAY,GAAI5J,MAAO,iDACxD2K,EAAKlB,gBACLkB,EAAKH,uBAETG,EAAKd,oBAAoB,KAAA,EAAA,OAAAqB,EAAA/b,EAAA,GAAA,EAAA4b,EAAA,KAAA,CAAA,CAAA,EAAA,IAAA,MAE/B,EAAAH,EAAA,GAzCoB9Z,EA0C1B,EACA2a,eAAc,SAACC,GACX,OAAIA,EAAQ,KAAaA,EAAQ,KAC7BA,EAAQ,SAAqBA,EAAQ,MAAMC,QAAQ,GAAK,OACpDD,EAAK,SAAkBC,QAAQ,GAAK,KAChD,EACA9B,kBAAiB,WACb,GAAK9Z,KAAK2U,YAEV,GAAK9F,EAAOqI,wBAAZ,CAKAlX,KAAK2U,YAAY4C,UAAUG,OAAO,UAElC,IAAIxH,EAAO,oCACXA,GAAQ,0DAER,IAAK,IAAI3R,EAAI,EAAGA,EAAIyB,KAAKoU,UAAU7U,OAAQhB,IAAK,CAC5C,IAAIoc,EAAM3a,KAAKoU,UAAU7V,GACrBwE,EAAO4X,EAAId,UAAY,WACvB9W,EAAKxD,OAAS,KAAIwD,EAAOA,EAAK+O,UAAU,EAAG,IAAM,OACrD5B,GAAQ,+IAAiJlQ,KAAK6b,WAAWlB,EAAId,UAAY,IAAM,KAC/L3J,GAAQ,qEACRA,GAAQlQ,KAAK6b,WAAW9Y,GACxBmN,GAAQ,yGAA2G3R,EAAI,yBAA2ByB,KAAKuU,2BAA6B,YAAc,IAAM,aACxMrE,GAAQ,SACZ,CAEA,IAAK,IAAI7P,EAAI,EAAGA,EAAIL,KAAKyU,aAAalV,OAAQc,IAAK,CAC/C,IAAIyb,EAAa9b,KAAKyU,aAAapU,GAC/B0b,EAAaD,EAAWjC,UAAY,OACpCmC,EAAWF,EAAW7L,OAAS,gBAC/B8L,EAAWxc,OAAS,KAAIwc,EAAaA,EAAWjK,UAAU,EAAG,IAAM,OACvE5B,GAAQ,8IAAgJlQ,KAAK6b,YAAYC,EAAWjC,UAAY,IAAM,KAAOmC,GAAY,KACzN9L,GAAQ,6EACRA,GAAQlQ,KAAK6b,WAAWE,GACxB7L,GAAQ,2GAA6G7P,EAAI,mCACzH6P,GAAQ,SACZ,CAEIlQ,KAAKsU,cACLpE,GAAQ,mIACRA,GAAQ,6GACRA,GAAQ,WAGZA,GAAQ,wNAA0NlQ,KAAKuU,2BAA6B,YAAc,IAAM,IACxRrE,GAAQ,wCACsB,IAA1BlQ,KAAKoU,UAAU7U,QAAiBS,KAAKsU,cACrCpE,GAAQ,8BAEZA,GAAQ,YACRA,GAAQ,SACJrB,EAAOoN,0BACP/L,GAAQ,yDAA2DlQ,KAAK6b,WAAWhN,EAAOoN,yBAA2B,UAGzH/L,GAAQ,SAERlQ,KAAK2U,YAAYuH,gBAAgB/L,UAAUC,SAASF,EAAM,CAAEiM,qBAAqB,KAKjF,IAFA,IAAI7D,EAAOtY,KACPoc,EAAepc,KAAK2U,YAAY0H,iBAAiB,oBAC5CC,EAAI,EAAGA,EAAIF,EAAa7c,OAAQ+c,IACrCF,EAAaE,GAAGC,iBAAiB,QAAU,SAAUvL,GACjD,OAAO,SAAUjT,GAGb,GAFAA,EAAEoZ,iBACFpZ,EAAEqZ,mBACEkB,EAAK/D,2BAAT,CAIA,IAAIiI,EAAclE,EAAKlE,UAAUpD,GAC7BwL,GAAalE,EAAKoC,eAAe8B,EAHrC,CAIJ,CACJ,CAX2C,CAWxCC,SAASL,EAAaE,GAAGI,aAAa,qBAK7C,IADA,IAAIC,EAAoB3c,KAAK2U,YAAY0H,iBAAiB,sBACjDle,EAAI,EAAGA,EAAIwe,EAAkBpd,OAAQpB,IAC1Cwe,EAAkBxe,GAAGoe,iBAAiB,QAAU,SAAUvL,GACtD,OAAO,SAAUjT,GACbA,EAAEoZ,iBACFpZ,EAAEqZ,kBACFkB,EAAK7D,aAAa+G,OAAOxK,EAAK,GAC9BsH,EAAKwB,mBACT,CACJ,CAPgD,CAO7C2C,SAASE,EAAkBxe,GAAGue,aAAa,uBAIlD,IAAIE,EAAS5c,KAAK2U,YAAYnO,cAAc,wBACxCoW,GACAA,EAAOL,iBAAiB,QAAS,SAAUxe,GACvCA,EAAEoZ,iBACEmB,EAAK/D,4BAGT+D,EAAKP,kBACT,EA3FJ,MAFI/X,KAAK2U,YAAY4C,UAAUC,IAAI,SA+FvC,EACAqE,WAAU,SAAClW,GACP,IAAIkX,EAAMhX,SAASC,cAAc,OAEjC,OADA+W,EAAI9W,YAAcJ,EACXkX,EAAI7W,SACf,EACAqU,4BAA2B,SAACjB,EAAW0D,GACnC,IAAK1D,GAAkC,iBAAdA,EACrB,OAAO0D,EAGX,IAAItX,EAAU4T,EAAU3T,OACxB,IAAKD,EACD,OAAOsX,EAGX,GAAItX,EAAQuX,WAAW,MAAQvX,EAAQuX,WAAW,KAC9C,IACI,IAAIC,EAASrN,KAAKC,MAAMpK,GACpBqE,GAAUmT,aAAM,EAANA,EAAQ/M,SAAS+M,aAAM,EAANA,EAAQnT,WAAWmT,aAAM,EAANA,EAAQvU,SAASuU,aAAM,EAANA,EAAQC,QAC3E,MAA0B,iBAAZpT,GAAwBA,EAAQpE,OACxCoE,EAAQpE,OACRqX,CACV,CAAE,MAAOlR,GACL,OAAOkR,CACX,CAGJ,MAAI,UAAU9Z,KAAKwC,GACRsX,EAGJtX,CACX,EACA0X,6BAA4B,SAACC,GACzB,IAAKA,EACD,OAAO,KAGX,IAAIzR,EAAoC,iBAArByR,EAAWzR,MAAqByR,EAAWzR,MAAMjG,OAAS,GACzE2X,EAAkC,iBAApBD,EAAWC,KAAoBD,EAAWC,KAAK3X,OAAS,GACtE4X,EAA0C,iBAAxBF,EAAWE,SAAwBF,EAAWE,SAAS5X,OAAS,GAClF6X,IAA8BH,EAAWG,0BAE7C,OAAK5R,GAAU0R,GAASC,GAAaC,EAI9B,CACH5R,MAAOA,EACP0R,KAAMA,EACNC,SAAUA,EACVC,0BAA2BA,GAPpB,IASf,EACAC,kBAAiB,SAAC1T,GACd,IAAIsT,EAAatT,EAAU7J,KAAKkd,6BAA6BrT,EAAQsT,YAAc,KACnF,OAAOA,GAAcA,EAAWzR,MAAQyR,EAAWzR,MAAQ1L,KAAK4D,cACpE,EACA4Z,wBAAuB,SAAC3T,GACpB,IAAIsT,EAAatT,EAAU7J,KAAKkd,6BAA6BrT,EAAQsT,YAAc,KAC/EM,EAAU,CAAC,oBAQf,OANIN,GAAcA,EAAWE,SACzBI,EAAQxa,KAAKka,EAAWE,UAExBI,EAAQxa,KAAK,8BAGVwa,CACX,EACAC,wBAAuB,SAAC7T,EAASvB,GAC7B,IAAI6U,EAAatT,EAAU7J,KAAKkd,6BAA6BrT,EAAQsT,YAAc,KACnF,MAAO,CAACnd,KAAK2d,2BAA2B9T,EAASvB,GAAS,oBAAsB,cAAe6U,GAAcA,EAAWE,SAAWF,EAAWE,SAAW,GAC7J,EACAO,iBAAgB,SAAC/T,GACb,IAAIsT,EAAatT,EAAU7J,KAAKkd,6BAA6BrT,EAAQsT,YAAc,KACnF,OAAOA,GAAcA,EAAWC,KAAOD,EAAWC,KAAO,aAC7D,EACAO,2BAA0B,SAAC9T,EAASvB,GAChC,IAAI6U,EAAatT,EAAU7J,KAAKkd,6BAA6BrT,EAAQsT,YAAc,KACnF,QAAStT,GACLA,EAAQgK,aACRvL,IAAUtI,KAAK6W,sBACbsG,GAAcA,EAAWG,0BACnC,EACMO,gBAAe,WAAG,IAAAC,EAAA9d,KAAA,OAAAe,kBAAAjD,eAAAuC,EAAA,SAAA0d,IAAA,IAAAC,EAAA,OAAAlgB,eAAAsC,EAAA,SAAA6d,GAAA,cAAAA,EAAAjf,EAAAif,EAAA9f,GAAA,KAAA,EAiOjB,OAhOH2f,EAAKI,YAAa,IAAIC,QAAQC,sBACzBC,QAAQxP,EAAOqE,eACfoL,yBACAC,QAILT,EAAKI,WAAWM,4BAA8B,IAC9CV,EAAKI,WAAWO,gCAAkC,KAElDX,EAAKI,WAAWQ,GAAG,cAAe,SAACtR,GAAS,IAAAuR,EACxCb,EAAKxD,kBAAkBlN,EAAK4L,WAAW,GACvC8E,EAAK7J,SAAW,GAChB6J,EAAK1J,UAAYhH,EAAKgH,WAAa,GACnC0J,EAAKrJ,aAAe,IAEN,QAAdkK,EAACvR,EAAK6G,gBAAQ,IAAA0K,EAAAA,EAAI,IAAI1X,QAAQ,SAAA2X,GAC1Bd,EAAKe,WAAWD,GAEhBd,EAAKgB,UAAU,WACXxQ,EAAsBsQ,EAC1B,EACJ,GAGAd,EAAKgB,UAAU,WACXhB,EAAKiB,yBACT,GAI6B,IAAzBjB,EAAK7J,SAAS1U,QAAgBsP,EAAOmQ,gBACrClB,EAAK3J,OAAStF,EAAOmQ,cACrBlB,EAAKmB,cAEb,GAEAnB,EAAKI,WAAWQ,GAAG,eAAgB,SAACzO,GAChChB,QAAQgB,MAAM,kBAAmBA,GAE7B6N,EAAKjJ,aACLiJ,EAAKoB,gBAGLlM,GAA+D,mBAAtCA,EAAemM,oBACxCnM,EAAemM,mBAAmBrB,EAAM7N,EAAOpB,EAEvD,GAEAiP,EAAKI,WAAWQ,GAAG,eAAgB,SAACU,EAAWC,GAC3C,IAAIT,EAAMd,EAAK7J,SAASqL,KAAK,SAAAjf,GAAC,OAAIA,EAAEkf,KAAOH,CAAS,GAChDR,IACAA,EAAIS,WAAaA,EAEzB,GAEAvB,EAAKI,WAAWQ,GAAG,oBAAqB,SAAC1F,EAAWrT,EAAM6Z,GACtD,GAAI1B,EAAK3H,oBACL,IAAKqJ,GAAW7Z,EAAM,CAClBmY,EAAK2B,+BAAiC9Z,EACtC,IACIuK,EAAO,oCADGvK,EAAKkN,QAAQ,KAAM,SAASA,QAAQ,KAAM,QAAQA,QAAQ,KAAM,QACnB,OAGtDiL,EAAK4B,6BAUN5B,EAAK4B,4BAA4B1V,QAAUrE,EAC3CmY,EAAK4B,4BAA4B3S,YAAcmD,IAV/C4N,EAAK6B,kBACL7B,EAAK4B,4BAA8B,CAC/B5I,KAAM,OACN9M,QAASrE,EACToH,YAAamD,EACb0P,WAAW,GAEf9B,EAAK7J,SAAShR,KAAK6a,EAAK4B,8BAK5B5B,EAAK+B,gBACT,OAIAla,IAASmY,EAAKgC,kBACdhC,EAAK3J,OAAS2J,EAAK/I,mBAAqBpP,EACpCmY,EAAKtK,eACLsK,EAAKtK,aAAa5T,MAAQke,EAAK3J,OAC/B2J,EAAKtK,aAAauM,cAAc,IAAIC,MAAM,WAGtD,GAEAlC,EAAKI,WAAWQ,GAAG,iCAAkC,SAAC1F,EAAWrT,GAC7D,GAAIA,EAAM,CAKN,GAJAmY,EAAKmC,YAIDnC,EAAKoC,8BAA+B,CACpC,IAAIC,EAASrC,EAAK7J,SAAS6J,EAAKoC,8BAA8B5X,OAC1D6X,IACAA,EAAOtM,aAAc,GAEzBiK,EAAKoC,8BAAgC,IACzC,CAGA,GAAIpC,EAAK4B,4BAA6B,CAClC,IAAIU,EAAUza,EAAKkN,QAAQ,KAAM,SAASA,QAAQ,KAAM,QAAQA,QAAQ,KAAM,QAC9EiL,EAAK4B,4BAA4B1V,QAAUrE,EAC3CmY,EAAK4B,4BAA4B3S,YAAc,MAAQqT,EAAU,OACjEtC,EAAK4B,4BAA4BE,WAAY,EAC7C9B,EAAK4B,4BAA8B,IACvC,MACI5B,EAAKe,WAAW,CACZ/H,KAAM,OACN9M,QAASrE,IAGjBmY,EAAK+B,gBACT,CACJ,GAEA/B,EAAKI,WAAWQ,GAAG,oCAAqC,SAAC1F,EAAWoG,EAAWjO,EAAOkP,EAAYjX,EAAY+T,GAC1G,IAAKW,EAAKoC,8BAA+B,CACrCpC,EAAKmC,YACLnC,EAAKwC,sBAGL,IAAK,IAAIhE,EAAI,EAAGA,EAAIwB,EAAK7J,SAAS1U,OAAQ+c,IAClCwB,EAAK7J,SAASqI,GAAGzI,cACjBiK,EAAK7J,SAASqI,GAAGzI,aAAc,GAIvC,IAAI0M,EAAWzC,EAAK7J,SAAS1U,OACzBihB,EAAa,CACbjB,GAAIH,EACJtI,KAAM,YACN9M,QAAS,GACT+C,YAAa,GACb8G,aAAa,EACbwL,WAAY,KACZlC,WAAYW,EAAKZ,6BAA6BC,GAC9C/T,WAAY,CAAC,GAEjB0U,EAAK7J,SAAShR,KAAKud,GACnB1C,EAAKoC,8BAAgC,CAAE5X,MAAOiY,EAAUvW,QAAS,GACrE,CAEA8T,EAAKoC,8BAA8BlW,SAAWmH,EAC9C,IAAIyN,EAAMd,EAAK7J,SAAS6J,EAAKoC,8BAA8B5X,OACvDsW,IACKA,EAAIzB,aACLyB,EAAIzB,WAAaW,EAAKZ,6BAA6BC,IAEvDyB,EAAI7U,WAAa+T,EAAKoC,8BAA8BlW,QACpD4U,EAAIxV,WAAaD,EAAoBvK,OAAOyJ,OAAO,CAAC,EAAGuW,EAAIxV,YAAc,CAAC,EAAGA,GAAc,CAAC,IAC5FQ,EAA0BgV,EAAKA,EAAIxV,YACnC0U,EAAKgB,UAAU,WACXxQ,EAAsBsQ,GACtBd,EAAK+B,gBACT,GAER,GAEA/B,EAAKI,WAAWQ,GAAG,uCAAwC,SAAC1F,EAAWoG,EAAWhW,GAC9E,GAAI0U,EAAKoC,8BAA+B,CACpC,IAAItB,EAAMd,EAAK7J,SAAS6J,EAAKoC,8BAA8B5X,OACvDsW,IACAA,EAAI/K,aAAc,EAClB+K,EAAIxV,WAAaD,EAAoBvK,OAAOyJ,OAAO,CAAC,EAAGuW,EAAIxV,YAAc,CAAC,EAAGA,GAAc,CAAC,IAC5FQ,EAA0BgV,EAAKA,EAAIxV,aAEvC0U,EAAKoC,8BAAgC,IACzC,CACJ,GAEApC,EAAKI,WAAWQ,GAAG,oBAAqB,SAAC1F,EAAWyH,EAAaC,GAC7D,GAAID,EAAa,CAGb,IAFA,IAAME,EAAeC,KAAKH,GACpB9E,EAAQ,IAAIkF,WAAWF,EAAaphB,QACjChB,EAAI,EAAGA,EAAIoiB,EAAaphB,OAAQhB,IACrCod,EAAMpd,GAAKoiB,EAAaG,WAAWviB,GAEvCuf,EAAKzI,YAAYpS,KAAK0Y,EAC1B,CACJ,GAEAmC,EAAKI,WAAWQ,GAAG,uBAAwB,SAAC1F,GACxC8E,EAAKiD,oBACT,GAEAjD,EAAKI,WAAWQ,GAAG,sBAAuB,SAACsC,GACvClD,EAAKmD,oBAAoBD,EAC7B,GAEAlD,EAAKI,WAAWQ,GAAG,qBAAsB,SAACsC,GACtClD,EAAKoD,mBAAmBF,EAC5B,GAEAlD,EAAKI,WAAWQ,GAAG,qBAAsB,SAACyC,GACtCrD,EAAKsD,mBAAmBD,EAC5B,GAEArD,EAAKI,WAAWmD,eAAe,WAC3BpS,QAAQC,KAAK,2BACjB,GAEA4O,EAAKI,WAAWoD,cAAc,WAC1BrS,QAAQsS,KAAK,yBAETzD,EAAKnK,kBACLmK,EAAKrD,sBAEb,GAEAqD,EAAKI,WAAWsD,QAAQ,SAACvR,GACjB6N,EAAKhK,kBAIL7D,GACAhB,QAAQC,KAAK,wCAAyCe,EAAMpG,SAAWoG,EAE/E,GAAGgO,EAAAjf,EAAA,EAAAif,EAAA9f,EAAA,EAGO2f,EAAKI,WAAWnN,QAAO,KAAA,EAAAkN,EAAA9f,EAAA,EAAA,MAAA,KAAA,EAAA8f,EAAAjf,EAAA,EAAAgf,EAAAC,EAAA9e,EAE7B8P,QAAQgB,MAAM,6BAA4B+N,GAAO,KAAA,EAAA,OAAAC,EAAA7e,EAAA,GAAA,EAAA2e,EAAA,KAAA,CAAA,CAAA,EAAA,IAAA,GAtOjChd,EAwOxB,EACA0gB,mBAAkB,SAAC5X,GAAS,IAAA6X,EAAA1hB,KACH,cAAjB6J,EAAQiN,OACRjN,EAAQsT,WAAand,KAAKkd,6BAA6BrT,EAAQsT,aAG/DtT,EAAQG,UAAYH,EAAQkD,cAC5BlD,EAAQkD,YAAcC,EAAqBnD,EAAQG,QAASH,IAEhE7J,KAAK2hB,UAAU,IAAIC,YAAY,4BAA6B,CAAE3E,OAAQ,CAAEpT,QAASA,MACjF7J,KAAKiU,SAAShR,KAAK4G,GAEnB7J,KAAK8e,UAAU,WACX4C,EAAKC,UAAU,IAAIC,YAAY,2BAA4B,CAAE3E,OAAQ,CAAEpT,QAASA,KACpF,EACJ,EACAgV,WAAU,SAAChV,GAAS,IAOKgY,EAPLC,EAAA9hB,WAGW2Q,IAAvB9G,EAAQwV,aACRxV,EAAQwV,WAAa,MAGrBxV,EAAQG,WACRH,EAAQE,WAA+B,QAArB8X,EAAGhY,EAAQE,kBAAU,IAAA8X,EAAAA,EAAIhY,EAAQG,QACnDJ,EAA0BC,EAASA,EAAQT,aAG/CpJ,KAAKyhB,mBAAmB5X,GACxB7J,KAAK2f,kBAEL3f,KAAK8e,UAAU,WAEXxQ,EAAsBzE,GACtBiY,EAAKjC,gBACT,EACJ,EACAkC,YAAW,SAAC9N,GAER,IAFkB,IAAA+N,EAAAhiB,KAETzB,EAAI,EAAGA,EAAI0V,EAAS1U,OAAQhB,IACjCyB,KAAKyhB,mBAAmBxN,EAAS1V,IAGrCyB,KAAK2f,kBACL3f,KAAK8e,UAAU,WACXkD,EAAKnC,gBACT,EACJ,EACAF,gBAAe,WACP3f,KAAKsL,aACLtL,KAAKsL,YAAYiM,UAAUC,IAAI,UAEnCxX,KAAK4T,sBAAuB,CAChC,EACAqO,gBAAe,WACPjiB,KAAKsL,aACLtL,KAAKsL,YAAYiM,UAAUG,OAAO,UAEtC1X,KAAK4T,sBAAuB,CAChC,EACAsO,wBAAuB,WACnB,OAA0C,IAAnCrT,EAAOqT,uBAClB,EACAC,8BAA6B,WACzB,GAAIniB,KAAKkiB,0BACL,OAAO,EAGX,IAAME,EAAqBvT,EAAOwT,gCAAkC,gDAsBpE,OApBIriB,KAAKwT,eACLxT,KAAKwT,aAAa8O,UAAW,EAC7BtiB,KAAKwT,aAAa5T,MAAQ,GAC1BI,KAAKwT,aAAalI,YAAc8W,GAGhCpiB,KAAKyT,gBACLzT,KAAKyT,cAAc6O,UAAW,GAG9BtiB,KAAKuiB,mBACLviB,KAAKuiB,iBAAiBD,UAAW,EACjCtiB,KAAKuiB,iBAAiBC,MAAMC,QAAU,QAGtCziB,KAAK0iB,4BACL1iB,KAAK0iB,0BAA0BJ,UAAW,EAC1CtiB,KAAK0iB,0BAA0BF,MAAMC,QAAU,SAG5C,CACX,EACAd,UAAS,SAACgB,GACN9c,SAASka,cAAc4C,EAC3B,EACAC,YAAW,SAAC/Y,GACR,MAAwB,cAAjBA,EAAQiN,IACnB,EACAmI,YAAW,WACP,GAAKjf,KAAKmiB,gCAAV,CAIA,IAAIU,EAAgB7iB,KAAKmU,OAAO1O,OAE3Bod,IAKD7iB,KAAK6U,aACL7U,KAAKkf,gBAITlf,KAAK8f,iBAAkB,EAGnB9f,KAAKgW,oBACLhW,KAAKiU,SAASuH,OAAO,EAAGxb,KAAKiU,SAAS1U,QAG1CS,KAAK6e,WAAW,CACZ/H,KAAM,OACN9M,QAAS6Y,IAGb7iB,KAAK8iB,cAAc9iB,KAAK2Z,eAAgBkJ,EAAe,MACvD7iB,KAAKwT,aAAa5T,MAAQ,GAC1BI,KAAKmU,OAAS,GA5Bd,CA6BJ,EACA4O,eAAc,WAAG,IAAAC,EAAAhjB,MACTA,KAAK6U,aAAgB7U,KAAKke,YAI9B+E,UAAUC,aAAaC,aAAa,CAAEC,MAAO,CAAEC,kBAAkB,EAAMC,kBAAkB,EAAMC,iBAAiB,KAC3GziB,KAAK,SAAAkT,GACF,IAAIwP,EAAWC,cAAcC,gBAAgB,yBACvC,wBACAD,cAAcC,gBAAgB,0BAC1B,yBACA,aAEVV,EAAKlO,cAAgB,IAAI2O,cAAczP,EAAQ,CAC3CwP,SAAUA,EACVG,mBAAoB,QAGxBX,EAAKjO,mBAAqBiO,EAAK7O,OAC/B6O,EAAKlD,iBAAkB,EAEvB,IAAI8D,EAAU,IAAIzF,QAAQ0F,QACtB5K,EAAY+J,EAAKrJ,eACjBX,EAAYgK,EAAKtJ,gBAAkB,GACnCoK,EAAeljB,QAAQC,UAE3BmiB,EAAKlO,cAAcyH,iBAAiB,gBAAiB,SAACxe,GAC9CA,EAAEqP,MAAQrP,EAAEqP,KAAK2W,KAAO,IACxBD,EAAeA,EAAahjB,KAAIC,kBAAAjD,eAAAuC,EAAC,SAAA2jB,IAAA,IAAA5W,EAAA6W,EAAAtD,EAAAuD,EAAA,OAAApmB,eAAAsC,EAAA,SAAA+jB,GAAA,cAAAA,EAAAhmB,GAAA,KAAA,EAAA,OAAAgmB,EAAAhmB,EAAA,EACZJ,EAAEqP,KAAKgX,cAAa,KAAA,EAAjChX,EAAI+W,EAAAhlB,EACJ8kB,EAAa,IAAIpD,WAAWzT,GAC5BuT,EAAesD,EAAWI,OAAO,SAAUC,EAAKC,GAAQ,OAAOD,EAAME,OAAOC,aAAaF,EAAO,EAAG,IACnGL,EAASQ,KAAK/D,GAClBiD,EAAQrhB,KAAK2hB,GAAQ,KAAA,EAAA,OAAAC,EAAA/kB,EAAA,GAAA,EAAA4kB,EAAA,KAGjC,GAEAhB,EAAKlO,cAAcyH,iBAAiB,OAAQ,WACxCvI,EAAO2Q,YAAY1d,QAAQ,SAAA2d,GAAK,OAAIA,EAAMC,MAAM,GAChDf,EAAahjB,KAAK,WAAA,OAAM8iB,EAAQkB,UAAU,EAC9C,GAEA,IAAIlX,EAAWqV,UAAUrV,UAAY/H,SAASkf,gBAAgBxX,MAAQ,QACtEyV,EAAK9E,WAAW8G,KAAK,kBAAmB/L,EAAWD,EAAW4K,EAASJ,EAAU5V,GACjFoV,EAAKlO,cAAc/D,MAAM,KACzBiS,EAAKnO,aAAc,EACnBmO,EAAKiC,iBACT,GAAE,MACK,SAAArZ,GACHqD,QAAQgB,MAAM,4BAA6BrE,EAC/C,EACR,EACAsT,cAAa,WACJlf,KAAK6U,aAAgB7U,KAAK8U,gBAI/B9U,KAAK8U,cAAc+P,OACnB7kB,KAAK6U,aAAc,EACnB7U,KAAKilB,kBACT,EACAC,gBAAe,WACPllB,KAAK6U,YACL7U,KAAKkf,gBAELlf,KAAK+iB,gBAEb,EACAkC,gBAAe,WACNjlB,KAAKgV,YAINhV,KAAK6U,aACL7U,KAAKgV,UAAUuC,UAAUC,IAAI,iBAC7BxX,KAAKgV,UAAUhP,UAAY,qCAE3BhG,KAAKgV,UAAUuC,UAAUG,OAAO,iBAChC1X,KAAKgV,UAAUhP,UAAY,0CAEnC,EACA8c,cAAa,SAAC7J,EAAW4J,EAAesC,GAAkB,IAAAC,EAAAplB,KAElDA,KAAKgU,SACLhU,KAAKgU,OAAOqR,UACZrlB,KAAKgU,OAAS,MAGlBhU,KAAKslB,mBACLtlB,KAAKulB,sBACLvlB,KAAK+T,YAAa,EAElB,IAAI/J,EAAU,GACVZ,EAAa,CAAC,EACdoc,EAAiB,KAGjBC,EAAezlB,KAAKiU,SAAS1U,OAC7BmmB,EAAmB1lB,KAAK0Z,eAE5B1Z,KAAKgU,OAAShU,KAAKke,WAAWlK,OAAO,cAAeiF,EAAW4J,EAAe6C,EAAkBP,GAC3FQ,UAAU,CACPpjB,KAAM,SAACqjB,GACH,IAAI/b,EAAUub,EAAKnR,SAASwR,GAE5B,IAAK5b,EAAS,CAEN+b,EAAM5M,YAAc0M,GACpBN,EAAK9K,kBAAkBsL,EAAM5M,WAGjCoM,EAAK9E,sBAELmF,EAAeL,EAAKnR,SAAS1U,OAC7B,IAAIihB,EAAa,CACbjB,GAAIqG,EAAMxG,UACVtI,KAAM,YACNrO,MAAOmd,EAAMnd,MACbuB,QAAS,GACT+C,YAAa,GACb8G,aAAa,EACbwL,WAAY,MAGhB+F,EAAKnR,SAAShR,KAAKud,GAEnB3W,EAAU2W,CACd,CAMA,IAJIoF,EAAMnd,OAAWoB,EAAQpB,OAASoB,EAAQpB,QAAUmd,EAAMnd,QAC1DoB,EAAQpB,MAAQmd,EAAMnd,OAGtBmd,EAAMxc,YAA0C,WAA5BlG,QAAO0iB,EAAMxc,aAA2BxK,OAAO0T,KAAKsT,EAAMxc,YAAY7J,OAE1F,IAAA,IAAAsmB,EAAA,EAAAC,EAA2BlnB,OAAO2K,QAAQqc,EAAMxc,YAAWyc,EAAAC,EAAAvmB,OAAAsmB,IAAE,CAAA,IAAAE,EAAxDC,EAAAxjB,eAAAsjB,EAAAD,GAAA,GAAOnc,EAAGsc,EAAA,GAAEpmB,EAAKomB,EAAA,GAClB5c,EAAWM,GAAgC,QAA5Bqc,EAAGxe,EAAmB3H,UAAM,IAAAmmB,EAAAA,EAAI,CAAC,CACpD,CAGAH,EAAM5b,UAIF4b,EAAMvF,YAAcmF,GAAkBI,EAAMvF,aAAemF,IAC3Dxb,GAAW,QAGX4b,EAAMvF,aACNmF,EAAiBI,EAAMvF,YAG/BrW,GAAW4b,EAAM5b,SAIjBH,EAAQE,WAAaC,EACrBJ,EAA0BC,EAAST,GAEnCgc,EAAKnR,SAASwR,GAAgB5b,EAE9Bub,EAAKtG,UAAU,WACXxQ,EAAsBzE,GACtBub,EAAKvF,gBACT,EACJ,EACAiF,SAAU,WAAM,IAAAmB,EACZb,EAAKc,kBAAkB9c,EAAYqc,GACnCL,EAAKe,oBAEL,IAAIvH,EAAMwG,EAAKnR,SAASwR,GACpB7G,IACAA,EAAI/K,aAAc,GAGjB+K,GAAQA,EAAI5U,SAEbob,EAAK9E,sBAIL8E,EAAKjP,oBAAsBiP,EAAKjQ,qBAAuByJ,GAAOA,EAAI5U,SAClEob,EAAKgB,iBAAiBxH,EAAI5U,SAGnB,QAAXic,EAAAb,EAAKpR,cAAM,IAAAiS,GAAXA,EAAaZ,UACbD,EAAKpR,OAAS,IAClB,EACA/D,MAAO,SAACrE,GAAQ,IAAAya,EACZjB,EAAKc,kBAAkB9c,EAAYqc,GACnCL,EAAKe,oBAEL,IAAIvH,EAAMwG,EAAKnR,SAASwR,GACpB7G,IACAA,EAAI/K,aAAc,GAGtBuR,EAAK9E,sBAEA8E,EAAKtR,kBACNsR,EAAKvG,WAAWuG,EAAKkB,yBAGd,QAAXD,EAAAjB,EAAKpR,cAAM,IAAAqS,GAAXA,EAAahB,UACbD,EAAKpR,OAAS,KAEd/E,QAAQgB,MAAM,gBAAiBrE,EACnC,GAEZ,EACA0a,sBAAqB,WAOjB,MANiB,CACbxP,KAAM,YACN9M,QAAS,oGACT+C,YAAa,GAIrB,EACAmZ,kBAAiB,SAAC9c,EAAYqc,GAAc,IAAAc,EAAAvmB,KAGxC,GAFAoJ,EAAaD,EAAoBC,GAE7BxK,OAAO0T,KAAKlJ,GAAY7J,OAAQ,CAAA,IAAAinB,EAAAC,EAE5B5c,EAAU7J,KAAKiU,SAASwR,GAC5B5b,EAAQE,WAAkD,QAAxCyc,EAAqB,QAArBC,EAAG5c,EAAQE,kBAAU,IAAA0c,EAAAA,EAAI5c,EAAQG,eAAO,IAAAwc,EAAAA,EAAI,GAC9D5c,EAA0BC,EAAST,GAEnCpJ,KAAKiU,SAASwR,GAAgB5b,EAE9B7J,KAAK8e,UAAU,WACXxQ,EAAsBzE,GACtB0c,EAAK1G,gBACT,EACJ,CACJ,EACAyF,iBAAgB,WACZ,IAAIoB,EAAW1mB,KAAKyT,cAAciJ,aAAa,kBAE3CgK,GACA1mB,KAAKyT,cAAcyI,gBAAgB/L,UAAUC,SAASsW,EAAU,CAAEvK,qBAAqB,KAGvFnc,KAAKwT,cACLxT,KAAKwT,aAAamT,aAAa,WAAY,WAEnD,EACAR,kBAAiB,WACb,IAAIS,EAAY5mB,KAAKyT,cAAciJ,aAAa,mBAYhD,GAVIkK,GACA5mB,KAAKyT,cAAcyI,gBAAgB/L,UAAUC,SAASwW,EAAW,CAAEzK,qBAAqB,KAGxFnc,KAAKwT,eACLxT,KAAKwT,aAAaqT,gBAAgB,YAClC7mB,KAAKwT,aAAasT,SAIlB9mB,KAAK0T,cAEL,IADA,IAAIqT,EAAQ/mB,KAAK0T,cAAc2I,iBAAiB,sBACvC9d,EAAI,EAAGA,EAAIwoB,EAAMxnB,OAAQhB,IAC9BwoB,EAAMxoB,GAAGgZ,UAAUG,OAAO,qBAC1BqP,EAAMxoB,GAAGgZ,UAAUC,IAAI,eAK/B,IAASjZ,EAAI,EAAGA,EAAIyB,KAAKiU,SAAS1U,OAAQhB,IAClCyB,KAAKiU,SAAS1V,GAAGsV,cACjB7T,KAAKiU,SAAS1V,GAAGsV,aAAc,EAG3C,EACAmT,sBAAqB,SAACjpB,GAAG,IAAAkpB,GACjBlpB,SAAS,QAARkpB,EAADlpB,EAAGkf,cAAM,IAAAgK,OAAA,EAATA,EAAWC,YAAalnB,KAAK6V,eAIjC7V,KAAKigB,WAAU,EACnB,EACAkH,yBAAwB,WAAG,IAAAC,EAAApnB,KAClBA,KAAK0T,eAII1T,KAAK0T,cAAc2I,iBAAiB,4BAE1CpV,QAAQ,SAAAogB,GACZ,IACIC,EADcC,OAAOF,EAAO3K,aAAa,6BACb0K,EAAKzR,uBAErC0R,EAAO9P,UAAUiQ,OAAO,cAAeF,GACvCD,EAAOV,aAAa,QAASW,EAAY,cAAgB,aAC7D,EACJ,EACAG,kBAAiB,WAAG,IAAAC,EAAA1nB,KACXA,KAAK0T,eAII1T,KAAK0T,cAAc2I,iBAAiB,6BAE1CpV,QAAQ,SAAAogB,GACZ,IACIM,EADcJ,OAAOF,EAAO3K,aAAa,8BACdgL,EAAKjR,mBAChCmR,EAAWD,EACT,oCACA,mCAENN,EAAO9P,UAAUiQ,OAAO,eAAgBG,GACxCN,EAAO9P,UAAUiQ,OAAO,kBAAmBG,GAC3CN,EAAOV,aAAa,QAASgB,EAAWD,EAAK1jB,YAAc0jB,EAAK3jB,WAChEsjB,EAAOnL,gBAAgB/L,UAAUC,SAASwX,EAAU,CAAEzL,qBAAqB,IAC/E,EACJ,EACA0L,mBAAkB,SAACR,EAAQM,GACvB,GAAKN,EAAL,CAIA,IAAIO,EAAWD,EACT,oCACA,mCAENN,EAAO9P,UAAUiQ,OAAO,eAAgBG,GACxCN,EAAO9P,UAAUiQ,OAAO,kBAAmBG,GAC3CN,EAAOV,aAAa,QAASgB,EAAW3nB,KAAKgE,YAAchE,KAAK+D,WAChEsjB,EAAOnL,gBAAgB/L,UAAUC,SAASwX,EAAU,CAAEzL,qBAAqB,IAT3E,CAUJ,EACAiK,iBAAgB,SAACzgB,EAAMmiB,GAAY,IAAAC,EAAA/nB,KAC1BA,KAAKmV,qBAAwBxP,GAAS3F,KAAKke,aAIhDle,KAAKqV,YAAc,GACnBrV,KAAKuV,gBAAiB,EACtBvV,KAAKgoB,oBAAgCrX,IAAfmX,EAA2BA,GAAc,EAE/D9nB,KAAKke,WAAW+J,OAAO,mBAAoBjoB,KAAK2Z,eAAgB3Z,KAAK0Z,eAAgB/T,EAAM3F,KAAKoV,cAAa,MAClG,SAAAxJ,GACHqD,QAAQgB,MAAM,uBAAwBrE,GACtCmc,EAAKxS,gBAAiB,EACtBwS,EAAKpS,wBAA0B,EAC/BoS,EAAKC,gBAAkB,EACvBD,EAAKjJ,UAAU,WAAA,OAAMiJ,EAAKZ,0BAA0B,EACxD,GACR,EACAe,iBAAgB,SAACre,EAASvB,GAAO,IAAA6f,EAAAnoB,KACzBA,KAAK2V,yBAA2BrN,GAKpCtI,KAAKigB,WAAU,GACf9c,OAAO4c,cAAc,IAAI6B,YAAY,6BAA8B,CAC/D3E,OAAQ,CAAEiK,SAAUlnB,KAAK6V,kBAE7B7V,KAAK2V,uBAAyBrN,EAC9BtI,KAAK8e,UAAU,WAAA,OAAMqJ,EAAKhB,0BAA0B,GAEhDnnB,KAAK4V,cAActN,GACnBtI,KAAKooB,cAAcpoB,KAAK4V,cAActN,IAI1CtI,KAAKomB,iBAAiBvc,EAAQG,QAAS1B,IAhBnCtI,KAAKigB,WAiBb,EACAc,mBAAkB,WAAG,IAAAsH,EAAAroB,KACjB,GAAgC,IAA5BA,KAAKqV,YAAY9V,OAArB,CASA,IAGoC+oB,EAH9BC,EAAcvoB,KAAKqV,YAAYgP,OAAO,SAACmE,EAAK5C,GAAK,OAAK4C,EAAM5C,EAAMrmB,MAAM,EAAE,GAC1EkpB,EAAW,IAAI5H,WAAW0H,GAC5BG,EAAS,EAAEC,EAAAxmB,2BACKnC,KAAKqV,aAAW,IAApC,IAAAsT,EAAArmB,MAAAgmB,EAAAK,EAAAxqB,KAAAwB,MAAsC,CAAA,IAA3BimB,EAAK0C,EAAA1oB,MACZ6oB,EAASG,IAAIhD,EAAO8C,GACpBA,GAAU9C,EAAMrmB,MACpB,CAAC,CAAA,MAAAqM,GAAA+c,EAAA5qB,EAAA6N,EAAA,CAAA,QAAA+c,EAAA5pB,GAAA,CACDiB,KAAKqV,YAAc,GAEnB,IAAMwT,EAAO,IAAIC,KAAK,CAACL,GAAW,CAAEzW,KAAM,cAEtChS,KAAKgoB,gBAAkB,IACvBhoB,KAAK4V,cAAc5V,KAAKgoB,gBAAkBa,EAC1C7oB,KAAKgoB,gBAAkB,GAIvBhoB,KAAKwV,oBACLxV,KAAKsV,eAAerS,KAAK4lB,GAI7B7oB,KAAKooB,cAAcS,EAxBnB,MANS7oB,KAAKwV,qBAAsD,IAA/BxV,KAAKsV,eAAe/V,SACjDS,KAAKuV,gBAAiB,EACtBvV,KAAK2V,wBAA0B,EAC/B3V,KAAK8e,UAAU,WAAA,OAAMuJ,EAAKlB,0BAA0B,GA4BhE,EACAiB,cAAa,SAACS,GAAM,IAAAE,EAAA/oB,KACVuF,EAAMyjB,IAAIC,gBAAgBJ,GAC1BzF,EAAQ,IAAI8F,MAAM3jB,GAExBvF,KAAKyV,gBAAkBlQ,EACvBvF,KAAKwV,oBAAsB4N,EAC3BpjB,KAAKuV,gBAAiB,EAEtB6N,EAAM7G,iBAAiB,QAAS,WAC5BwM,EAAKvT,oBAAsB,KAC3BuT,EAAKtT,gBAAkB,KACvBuT,IAAIG,gBAAgB5jB,GACpBwjB,EAAKK,iBACT,GAEAhG,EAAM7G,iBAAiB,QAAS,WAC5BwM,EAAKvT,oBAAsB,KAC3BuT,EAAKtT,gBAAkB,KACvBuT,IAAIG,gBAAgB5jB,GACpBwjB,EAAKK,iBACT,GAEAhG,EAAMiG,OAAM,MAAO,SAAAzd,GACfqD,QAAQgB,MAAM,wBAAyBrE,GACvCmd,EAAKvT,oBAAsB,KAC3BuT,EAAKtT,gBAAkB,KACvBuT,IAAIG,gBAAgB5jB,GACpBwjB,EAAKzT,eAAiB,GACtByT,EAAKxT,gBAAiB,EACtBwT,EAAKpT,wBAA0B,EAC/BoT,EAAKjK,UAAU,WAAA,OAAMiK,EAAK5B,0BAA0B,EACxD,EACJ,EACAiC,gBAAe,WAAG,IAAAE,EAAAtpB,KACd,GAAIA,KAAKsV,eAAe/V,OAAS,EAAG,CAChC,IAAIgqB,EAAWvpB,KAAKsV,eAAekU,QACnCxpB,KAAKooB,cAAcmB,EACvB,MACIvpB,KAAKuV,gBAAiB,EACtBvV,KAAK2V,wBAA0B,EAC/B3V,KAAK8e,UAAU,WAAA,OAAMwK,EAAKnC,0BAA0B,GACpDnnB,KAAKypB,8BAEb,EACAxJ,UAAS,WAAG,IAAAyJ,EAAA1pB,KACJA,KAAKwV,sBACLxV,KAAKwV,oBAAoBmU,QACzB3pB,KAAKwV,oBAAoBoU,YAAc,EACvC5pB,KAAKwV,oBAAsB,MAE3BxV,KAAKyV,kBACLuT,IAAIG,gBAAgBnpB,KAAKyV,iBACzBzV,KAAKyV,gBAAkB,MAE3BzV,KAAKqV,YAAc,GACnBrV,KAAKsV,eAAiB,GACtBtV,KAAKuV,gBAAiB,EACtBvV,KAAK2V,wBAA0B,EAC/B3V,KAAK8e,UAAU,WAAA,OAAM4K,EAAKvC,0BAA0B,EACxD,EACA0C,uBAAsB,WACd7pB,KAAKmW,mBACLnW,KAAK8pB,uBAEL9pB,KAAK+pB,uBAEb,EACAA,sBAAqB,WAAG,IAAAC,EAAAhqB,KACfA,KAAKiW,0BAA2BjW,KAAKmW,oBAAuBnW,KAAKke,aAItEle,KAAKmW,oBAAqB,EAC1BnW,KAAKiqB,2BACLjqB,KAAKyf,+BAAiC,GACtCzf,KAAKkgB,8BAAgC,KACrClgB,KAAK0f,4BAA8B,KAGnC1f,KAAKohB,mBAAmB,sBACxB6B,UAAUC,aAAaC,aAAa,CAAEC,MAAO,CAAEC,kBAAkB,EAAMC,kBAAkB,EAAMC,iBAAiB,KAC3GziB,KAAK,SAAAkT,GACF,IAAIwP,EAAWC,cAAcC,gBAAgB,yBACvC,wBACAD,cAAcC,gBAAgB,0BAC1B,yBACA,aAEVsG,EAAKlV,cAAgB,IAAI2O,cAAczP,EAAQ,CAC3CwP,SAAUA,EACVG,mBAAoB,QAGxBqG,EAAKE,qBAAuB,IAAI/L,QAAQ0F,QACxCmG,EAAKG,oBAAsBnW,EAO3B,IAAIoW,EAAWjnB,OAAOknB,cAAgBlnB,OAAOmnB,mBACzCF,IACAJ,EAAKO,sBAAwB,IAAIH,EACjCJ,EAAKQ,sBAAwBR,EAAKO,sBAAsBE,iBACxDT,EAAKQ,sBAAsBE,QAAU,IACrBV,EAAKO,sBAAsBI,wBAAwB3W,GACzD4W,QAAQZ,EAAKQ,wBAG3B,IAAI1G,EAAeljB,QAAQC,UACvBgqB,EAAWb,EAAKQ,sBAGpBR,EAAKlV,cAAcyH,iBAAiB,gBAAiB,SAACxe,GAClD,GAAIA,EAAEqP,MAAQrP,EAAEqP,KAAK2W,KAAO,EAAG,CAG3B,GAAIiG,EAAKzU,gBAAkBsV,EAAU,CACjC,IAAIC,EAAW,IAAIjK,WAAWgK,EAASE,mBACvCF,EAASG,qBAAqBF,GAE9B,IADA,IAAItC,EAAM,EACDyC,EAAI,EAAGA,EAAIH,EAASvrB,OAAQ0rB,IAAOzC,GAAOsC,EAASG,GAClDzC,EAAMsC,EAASvrB,QAXN,IAefyqB,EAAK/J,WAEb,CAKA6D,EAAeA,EAAahjB,KAAIC,kBAAAjD,eAAAuC,EAAC,SAAA6qB,IAAA,IAAA9d,EAAA6W,EAAAtD,EAAAuD,EAAA,OAAApmB,eAAAsC,EAAA,SAAA+qB,GAAA,cAAAA,EAAAhtB,GAAA,KAAA,EAAA,OAAAgtB,EAAAhtB,EAAA,EACZJ,EAAEqP,KAAKgX,cAAa,KAAA,EAAjChX,EAAI+d,EAAAhsB,EACJ8kB,EAAa,IAAIpD,WAAWzT,GAC5BuT,EAAesD,EAAWI,OAAO,SAAUC,EAAKC,GAAQ,OAAOD,EAAME,OAAOC,aAAaF,EAAO,EAAG,IACnGL,EAASQ,KAAK/D,GAClB,IACIqJ,EAAKE,qBAAqB3nB,KAAK2hB,EACnC,CAAE,MAAOtY,GACL,CACH,KAAA,EAAA,OAAAuf,EAAA/rB,EAAA,GAAA,EAAA8rB,EAAA,IAET,CACJ,GAEAlB,EAAKlV,cAAcyH,iBAAiB,OAAQ,WACxCvI,EAAO2Q,YAAY1d,QAAQ,SAAA2d,GAAK,OAAIA,EAAMC,MAAM,GAChDf,EAAahjB,KAAK,WACd,IACIkpB,EAAKE,qBAAqBpF,UAC9B,CAAE,MAAOlZ,GACL,CAER,EACJ,GAEA,IAAIqN,EAAY+Q,EAAKrQ,eACjBX,EAAYgR,EAAKtQ,gBAAkB,GACnC9L,EAAWqV,UAAUrV,UAAY/H,SAASkf,gBAAgBxX,MAAQ,QAEtEyc,EAAK9L,WAAW8G,KAAK,oBAAqB/L,EAAWD,EAAWgR,EAAKE,qBAAsB1G,EAAU5V,GACrGoc,EAAKlV,cAAc/D,MAAM,KACzBiZ,EAAKnV,aAAc,CACvB,GAAE,MACK,SAAAjJ,GACHqD,QAAQgB,MAAM,4BAA6BrE,GAC3Coe,EAAK7T,oBAAqB,EAC1B6T,EAAKC,0BACT,GACR,EACAH,qBAAoB,WAChB,GAAK9pB,KAAKmW,mBAAV,CA6BA,GAzBAnW,KAAKmW,oBAAqB,EAC1BnW,KAAKiqB,2BAGDjqB,KAAKke,YACLle,KAAKke,WAAW+J,OAAO,oBAAmB,MAAO,WAAc,GAG/DjoB,KAAK6U,aAAe7U,KAAK8U,gBACzB9U,KAAK8U,cAAc+P,OACnB7kB,KAAK6U,aAAc,GAGvB7U,KAAKigB,YACLjgB,KAAKyf,+BAAiC,GACtCzf,KAAK0f,4BAA8B,KAG/B1f,KAAKuqB,wBACLvqB,KAAKuqB,sBAAsBa,QAAO,MAAO,WAAc,GACvDprB,KAAKuqB,sBAAwB,KAC7BvqB,KAAKwqB,sBAAwB,MAI7BxqB,KAAKkgB,8BAA+B,CACpC,IAAItB,EAAM5e,KAAKiU,SAASjU,KAAKkgB,8BAA8B5X,OACvDsW,IACAA,EAAI/K,aAAc,GAEtB7T,KAAKkgB,8BAAgC,IACzC,CAGA,IAAK,IAAI3hB,EAAI,EAAGA,EAAIyB,KAAKiU,SAAS1U,OAAQhB,IAClCyB,KAAKiU,SAAS1V,GAAGsV,cACjB7T,KAAKiU,SAAS1V,GAAGsV,aAAc,GAKvC7T,KAAKihB,oBAAoB,CACrBjP,KAAM,qBACNhI,QAAS,sBACToT,KAAM,2BACNiO,aAAa,EACbC,cAAe,KAhDnB,CAkDJ,EACArB,yBAAwB,WACpB,GAAKjqB,KAAKkW,mBAIV,GAAIlW,KAAKmW,mBAAoB,CACzBnW,KAAKkW,mBAAmBqB,UAAUC,IAAI,SAAU,eAChDxX,KAAKkW,mBAAmBqB,UAAUG,OAAO,WAAY,mBAAoB,yBACzE1X,KAAKkW,mBAAmBzN,MAAQzI,KAAKkW,mBAAmBwG,aAAa,mBAAqB,mBAC1F,IAAI6O,EAAUvrB,KAAKkW,mBAAmBwG,aAAa,iBAC/C6O,GACAvrB,KAAKkW,mBAAmBgG,gBAAgB/L,UAAUC,SAASmb,EAAS,CAAEpP,qBAAqB,IAEnG,KAAO,CACHnc,KAAKkW,mBAAmBqB,UAAUG,OAAO,SAAU,eACnD1X,KAAKkW,mBAAmBqB,UAAUG,OAAO,WAAY,yBACrD1X,KAAKkW,mBAAmBqB,UAAUC,IAAI,oBACtCxX,KAAKkW,mBAAmBsV,OACxBxrB,KAAKkW,mBAAmBzN,MAAQzI,KAAKkW,mBAAmBwG,aAAa,qBAAuB,qBAC5F,IAAI+O,EAAYzrB,KAAKkW,mBAAmBwG,aAAa,mBACjD+O,GACAzrB,KAAKkW,mBAAmBgG,gBAAgB/L,UAAUC,SAASqb,EAAW,CAAEtP,qBAAqB,IAErG,CACJ,EACAuP,2BAA0B,WACtB,EAEJjC,6BAA4B,WAGxB,EAEJkC,eAAc,SAACC,GACX,GAAKA,EAAL,CAMA,IAAIC,EAAoBD,EAAQlP,aAAa,mBACzC1D,EAAYhZ,KAAK0Z,eACjByL,EAAmBnlB,KAAK2Z,eAEvBkS,GAAsB7S,EAO3BhZ,KAAK8iB,cAAc+I,EAAmB,KAAM1G,GALxClW,QAAQgB,MAAM,mFARlB,MAHIhB,QAAQgB,MAAM,oCAiBtB,EACA6b,iBAAgB,SAACC,EAASC,EAAOpsB,GAE7B,IAAMqsB,EAAUF,EAAQ7iB,cAAc6T,WAAW,QAAUgP,EAAU5oB,OAAO+oB,SAASC,OAASJ,EACxFxmB,EAAM,IAAIyjB,IAAIiD,GAIpB,OAFA1mB,EAAI6mB,aAAaxD,IAAIoD,EAAOpsB,GAErB2F,EAAI3C,UACf,EACA2iB,oBAAmB,WACfvlB,KAAK6e,WAAW,CACZ/H,KAAM,YACN/J,YAAa8B,EAAOxJ,mBAE5B,EACAib,oBAAmB,WACf,IAAM+L,EAAiBrsB,KAAKiU,SAAS1U,OAGrC,OAFAS,KAAKiU,SAAWjU,KAAKiU,SAAS3J,OAAO,SAAAsU,GAAG,MAAiB,cAAbA,EAAI9H,IAAoB,GAC/CuV,EAAiBrsB,KAAKiU,SAAS1U,MAExD,EACA0hB,oBAAmB,SAACD,GAAc,IAAAsL,EAAAtsB,KAC9B,GAAKghB,GAAiBA,EAAahP,KAAnC,CAGAhS,KAAKusB,yBAAyBvL,EAAahP,MAC3C,IAAIwa,EAAgBxsB,KAAKkU,cAAcuY,UAAU,SAAAtuB,GAAC,OAAIA,EAAE6T,OAASgP,EAAahP,IAAI,GAC9Ewa,GAAiB,EACjBxsB,KAAKkU,cAAcsH,OAAOgR,EAAe,EAAGxL,GAE5ChhB,KAAKkU,cAAcjR,KAAK+d,GAE5BhhB,KAAK0sB,4BAA4B1L,GACjChhB,KAAK8e,UAAU,WACXwN,EAAKzM,gBACT,EAXA,CAYJ,EACAqB,mBAAkB,SAACF,GACf,GAAKA,GAAiBA,EAAahP,KAAnC,CAGAhS,KAAKusB,yBAAyBvL,EAAahP,MAC3C,IAAIwa,EAAgBxsB,KAAKkU,cAAcuY,UAAU,SAAAtuB,GAAC,OAAIA,EAAE6T,OAASgP,EAAahP,IAAI,GAC9Ewa,GAAiB,IACjBxsB,KAAKkU,cAAcsH,OAAOgR,EAAe,EAAGxL,GAC5ChhB,KAAK0sB,4BAA4B1L,GALrC,CAOJ,EACA0L,4BAA2B,SAAC1L,GAAc,IAAA2L,EAAA3sB,KACjCghB,GAAiBA,EAAahP,MAASgP,EAAasK,iBAAiBtK,EAAasK,eAAiB,KAGxGtrB,KAAKoW,0BAA0B4K,EAAahP,MAAQ4a,WAAW,WAC3DD,EAAKvL,mBAAmBJ,EAAahP,KACzC,EAAGgP,EAAasK,eACpB,EACAiB,yBAAwB,SAACpL,GACrB,IAAI0L,EAAU7sB,KAAKoW,0BAA0B+K,GACxC0L,IAGLC,aAAaD,UACN7sB,KAAKoW,0BAA0B+K,GAC1C,EACAC,mBAAkB,SAACD,GACfnhB,KAAKusB,yBAAyBpL,GAC9BnhB,KAAKkU,cAAgBlU,KAAKkU,cAAc5J,OAAO,SAAAnM,GAAC,OAAIA,EAAE6T,OAASmP,CAAgB,EACnF,EACA4L,oBAAmB,SAAC5L,GAChBnhB,KAAKohB,mBAAmBD,EAC5B,EACA6L,yBAAwB,SAAC7L,EAAkB8L,GACvC,GAAKjtB,KAAKke,WAAV,CAGA,IAAIlF,EAAYhZ,KAAK0Z,eACrB1Z,KAAKke,WAAW+J,OAAO,2BAA4BjP,EAAWmI,EAAkB8L,GAAW,MAAO,SAAUrhB,GACxGqD,QAAQgB,MAAM,sCAAuCrE,EACzD,EAJA,CAKJ,EACAiU,eAAc,WAAG,IAAAqN,EAAAltB,KACRA,KAAK+T,YAGV6Y,WAAW,WACPM,EAAKxZ,cAAcyZ,UAAYD,EAAKxZ,cAAc0Z,aAAeF,EAAKxZ,cAAc2Z,YACxF,EAAG,GACP,EACAC,gBAAe,SAAC3K,GACZ3iB,KAAKmU,OAASwO,EAAMxK,OAAOvY,KAC/B,EACA+Z,aAAY,WACR,OAAO3Z,KAAKwT,aACNxT,KAAKwT,aAAakJ,aAAa,mBAC/B,IACV,EACA6Q,aAAY,SAACvU,GACJhZ,KAAKwT,cAIVxT,KAAKwT,aAAamT,aAAa,kBAAmB3N,GAAa,GACnE,EACAwU,aAAY,WACRxtB,KAAKkf,gBACLlf,KAAKytB,4BAA4B,sBACjCztB,KAAKutB,aAAa,IAClBvtB,KAAK2T,kBAAmB,EACxB3T,KAAK0tB,cAAgB,KACrB1tB,KAAKiU,SAAW,GAChBjU,KAAKoU,UAAY,GACjBpU,KAAKiiB,kBAEDjP,GAA2D,mBAAlCA,EAAe2a,gBACxC3a,EAAe2a,eAAe3tB,KAAM6O,EAE5C,EACA+e,gBAAe,WACX,GAAK5tB,KAAKmiB,gCAAV,CAIA,IAAMlJ,EAAYjZ,KAAK2Z,eAClBV,GAAcjZ,KAAKke,YAIxBle,KAAK6tB,kBAAkB5U,GAAU,MAAO,SAAArN,GAAG,OAAIqD,QAAQgB,MAAMrE,EAAI,EAPjE,CAQJ,EACMgO,0BAAyB,SAACX,GAAW,IAAA6U,EAAA9tB,KAAA,OAAAe,kBAAAjD,eAAAuC,EAAA,SAAA0tB,IAAA,IAAA/U,EAAA,OAAAlb,eAAAsC,EAAA,SAAA4tB,GAAA,cAAAA,EAAA7vB,GAAA,KAAA,EACJ,KAA/B6a,EAAY8U,EAAKpU,gBACR,CAAAsU,EAAA7vB,EAAA,EAAA,KAAA,CAAA,OAAA6vB,EAAA5uB,EAAA,EACF4Z,GAAS,KAAA,EAAA,GAGfC,GAAc6U,EAAK5P,WAAU,CAAA8P,EAAA7vB,EAAA,EAAA,KAAA,CAAA,OAAA6vB,EAAA5uB,EAAA,EACvB,MAAI,KAAA,EAAA,OAAA4uB,EAAA7vB,EAAA,EAGF2vB,EAAKD,kBAAkB5U,GAAU,KAAA,EAAA,OAAA+U,EAAA5uB,EAAA,EAAA4uB,EAAA7uB,GAAA,EAAA4uB,EAAA,GAVPhtB,EAW3C,EACA8sB,kBAAiB,SAAC5U,GAAW,IAAAgV,EAAAjuB,KACzB,OAAIA,KAAKqW,sBACErW,KAAKqW,sBAGX4C,GAAcjZ,KAAKke,YAIxBle,KAAKqW,sBAAwB,IAAIzV,QAAQ,SAACC,EAASqtB,GAC/CD,EAAK3X,uBAAyBzV,EAC9BotB,EAAK1X,uBAAyB2X,EAC9BD,EAAKzX,wBAA0BrT,OAAOypB,WAAW,WAC7CqB,EAAKR,4BAA4B,2CACrC,EAAG,KACP,GAEAztB,KAAKke,WAAW+J,OAAO,eAAgBhP,EAAW,MAAK,MAAO,SAAArN,GAC1DqiB,EAAKR,4BAA4B7hB,EACrC,GAEO5L,KAAKqW,uBAfDzV,QAAQC,QAAQ,KAgB/B,EACAstB,6BAA4B,SAACnV,GACrBhZ,KAAKsW,wBACLtW,KAAKsW,uBAAuB0C,GAGhChZ,KAAKouB,4BACT,EACAX,4BAA2B,SAACxd,GACpBjQ,KAAKuW,wBACLvW,KAAKuW,uBAAuBtG,GAGhCjQ,KAAKouB,4BACT,EACAA,2BAA0B,WAClBpuB,KAAKwW,yBACLrT,OAAO2pB,aAAa9sB,KAAKwW,yBAG7BxW,KAAKqW,sBAAwB,KAC7BrW,KAAKsW,uBAAyB,KAC9BtW,KAAKuW,uBAAyB,KAC9BvW,KAAKwW,wBAA0B,IACnC,EACA6X,cAAa,WAAG,IAAAC,EAAAtuB,KAMZ,GALAA,KAAKwT,aAAe3N,SAASW,cAAcqI,EAAOwE,sBAClDrT,KAAKyT,cAAgB5N,SAASW,cAAcqI,EAAOyE,2BACnDtT,KAAK0T,cAAgB7N,SAASW,cAAcqI,EAAOuE,8BACnDpT,KAAKsL,YAAczF,SAASW,cAAcqI,EAAO0f,8BAE5CvuB,KAAKwT,cAAiBxT,KAAKyT,eAAkBzT,KAAK0T,eAAkB1T,KAAKsL,aAQ1E,OAPA2D,QAAQgB,MAAM,yFAA0F,CACpGoD,qBAAsBxE,EAAOwE,qBAC7BC,0BAA2BzE,EAAOyE,0BAClCF,6BAA8BvE,EAAOuE,6BACrCmb,2BAA4B1f,EAAO0f,8BAGhC,EAGXvuB,KAAKmiB,gCAEL,IAAMnJ,EAAYhZ,KAAK0Z,eAMvB,IALK3G,GAAmBiG,GACpBhZ,KAAKwuB,YAAYxV,GAIjBnK,EAAOqI,yBAA2BrI,EAAO4f,sBACzCzuB,KAAK2U,YAAc9O,SAASW,cAAcqI,EAAO4f,qBAC7CzuB,KAAK2U,aAAa,CAClB3U,KAAK8Z,oBAGL,IAAI9B,EAAYnS,SAASC,cAAc,SACvCkS,EAAUhG,KAAO,OACjBgG,EAAUuH,GAAK,oBACfvH,EAAU0W,UAAY,SACtB1W,EAAU2W,UAAW,EACjB9f,EAAO+f,oBACP5W,EAAU6W,OAAShgB,EAAO+f,mBAE9B5W,EAAUuE,iBAAiB,SAAU,SAACxe,GAAC,OAAKuwB,EAAKpW,sBAAsBna,EAAE,GACzEiC,KAAK2U,YAAYma,cAAcC,YAAY/W,GAG3C,IAAIX,EAAYrX,KAAKwT,aAAexT,KAAKwT,aAAa8D,QAAQ,0CAA4C,KACtGD,IACAA,EAAUkF,iBAAiB,WAAY,SAACxe,GAAC,OAAKuwB,EAAKrX,eAAelZ,EAAE,GACpEsZ,EAAUkF,iBAAiB,YAAa,SAACxe,GAAC,OAAKuwB,EAAK7W,gBAAgB1Z,EAAE,GACtEsZ,EAAUkF,iBAAiB,OAAQ,SAACxe,GAAC,OAAKuwB,EAAK3W,WAAW5Z,EAAE,GAEpE,CAIJiC,KAAK0T,cAAc6I,iBAAiB,SAAU,WAC1C,GAAK+R,EAAKta,OAAV,CAGA,IACMgb,EAAWV,EAAK5a,cAAc0Z,aAAekB,EAAK5a,cAAc2Z,aAAeiB,EAAK5a,cAAcyZ,WADtF,GAElBmB,EAAKva,WAAaib,CAHlB,CAIJ,GAEAhvB,KAAKwT,aAAa+I,iBAAiB,UAAW,SAAAoG,GAEvB,MAAf2L,EAAKta,SAIS,UAAd2O,EAAMjZ,KAAoBiZ,EAAMsM,WAChCtM,EAAMxL,iBACNmX,EAAK7a,cAAcwE,SAE3B,GAEAjY,KAAKwT,aAAa+I,iBAAiB,QAAS,SAACxe,GACzCuwB,EAAKhB,gBAAgBvvB,GAEjBA,EAAEoa,OAAOvY,MAAM6F,OACf6oB,EAAK7a,cAAcoT,gBAAgB,YAEnCyH,EAAK7a,cAAckT,aAAa,YAAY,EAEpD,GAEA3mB,KAAKyT,cAAc8I,iBAAiB,QAAS,WAEzC,GAAmB,MAAf+R,EAAKta,OAoBTsa,EAAKrP,mBAZD,GAPAqP,EAAKta,OAAOqR,UACZiJ,EAAKta,OAAS,KAEdsa,EAAKnI,oBACLmI,EAAKhO,sBAGDgO,EAAKra,SAAS1U,OAAS,EAAG,CAC1B,IAAM2vB,EAAUZ,EAAKra,SAASqa,EAAKra,SAAS1U,OAAS,GAChC,cAAjB2vB,EAAQpY,MAAyBoY,EAAQllB,QAElCklB,EAAQrb,cACfqb,EAAQrb,aAAc,GAFtBya,EAAKra,SAASkb,KAItB,CAMR,GAIA,IAFA,IAAMC,EAAmBvpB,SAASwpB,uBAAuB,4BAEhD9wB,EAAI,EAAGA,EAAI6wB,EAAiB7vB,OAAQhB,IACzC6wB,EAAiB7wB,GAAGge,iBAAiB,QAAS,SAACxe,GAC3CA,EAAEoZ,iBACFmX,EAAK3C,eAAe5tB,EAAEoa,OAC1B,GAGJ,IAAMmX,EAAezpB,SAASwpB,uBAAuB,6BAErD,IAAS9wB,EAAI,EAAGA,EAAI+wB,EAAa/vB,OAAQhB,IACrC+wB,EAAa/wB,GAAGge,iBAAiB,QAAS,SAACxe,GACvCA,EAAEoZ,iBAEF,IAAI6B,EAAYjb,EAAEoa,OAAOuE,aAAa,mBAEjC1D,GAMLsV,EAAKE,YAAYxV,GACjBsV,EAAKiB,kBANDtgB,QAAQgB,MAAM,mFAOtB,GAKJ,IAFA,IAAMuf,EAAkB/tB,MAAME,QAAQkN,EAAOoF,UAAYpF,EAAOoF,SAAW,GAElE1V,EAAI,EAAGA,EAAIixB,EAAgBjwB,OAAQhB,IACxCyB,KAAK6e,WAAW2Q,EAAgBjxB,IAsDpC,OAlDAyB,KAAK8e,UAAU,WACXwP,EAAKvP,yBACT,GAGI/e,KAAK0T,eACL1T,KAAK0T,cAAc6I,iBAAiB,QAAS,SAACxe,GAC1C,IAAI0xB,EAAM1xB,EAAEoa,OAAOb,QAAQ,qBAC3B,GAAKmY,EAAL,CAIA,IAAIC,EAAQD,EAAInY,QAAQ,mBAAqBmY,EAAInY,QAAQ,OACzD,GAAKoY,EAAL,CAIA,IAAIC,EAASD,EAAMlpB,cAAc,QACjC,GAAImpB,EAAQ,CACR1M,UAAU2M,UAAUC,UAAUF,EAAO5pB,aACrC,IAAI+pB,EAAajhB,EAAO5K,gBAAkB,UAC1CwrB,EAAIzpB,UAAY,qCAAuC8pB,EACvDlD,WAAW,WACP6C,EAAIzpB,UAAY,oCACpB,EAAG,IACP,CAVA,CALA,CAgBJ,GAIAhG,KAAKiV,qBAAuBpG,EAAOkhB,2BACnC/vB,KAAKgV,UAAYnP,SAASW,cAAcqI,EAAOkhB,0BAC3C/vB,KAAKgV,YACLhV,KAAKgV,UAAUwN,MAAMC,QAAU,GAC/BziB,KAAKgV,UAAUuH,iBAAiB,QAAS,WACrC+R,EAAKpJ,iBACT,KAKJllB,KAAKiW,yBAA2BpH,EAAOmhB,oCACvChwB,KAAKkW,mBAAqBrQ,SAASW,cAAcqI,EAAOmhB,mCACpDhwB,KAAKkW,oBACLlW,KAAKkW,mBAAmBqG,iBAAiB,QAAS,WAC9C+R,EAAKzE,wBACT,KAID,CACX,EACA2E,YAAW,SAACxV,GACRhZ,KAAKke,WAAW+J,OAAO,cAAejP,GAAU,MAAO,SAAApN,GAAG,OAAIqD,QAAQgB,MAAMrE,EAAI,EACpF,EACA6O,qBAAoB,WAEhB,IAAIzB,EAAYhZ,KAAK0Z,eACjBV,GACAhZ,KAAKwuB,YAAYxV,EAEzB,EACAsB,kBAAiB,SAACtB,EAAWiX,IACrBjwB,KAAK2T,kBAAqBsc,GAO9BjwB,KAAK2hB,UAAU,IAAIC,YAAY,gCAAiC,CAAE3E,OAAQ,CAAEjE,UAAWA,MACvFhZ,KAAKutB,aAAavU,GAClBhZ,KAAK2T,kBAAmB,EACxB3T,KAAKmuB,6BAA6BnV,GAE9BhG,GAAiE,mBAAxCA,EAAekd,sBACxCld,EAAekd,qBAAqBlwB,KAAMgZ,EAAWnK,IAZjDmK,GAAahZ,KAAK0Z,iBAAmBV,GACrChZ,KAAKmuB,6BAA6BnV,EAa9C,EACAU,aAAY,WACR,IAAIV,EAAYhZ,KAAKwT,aACfxT,KAAKwT,aAAakJ,aAAa,mBAC/B,KAMN,OAJK1D,GAAahG,GAA6D,mBAApCA,EAAemd,mBACtDnX,EAAYhG,EAAemd,iBAAiBnwB,KAAM6O,IAG/CmK,CACX,EACAoX,wBAAuB,WACfpwB,KAAK0W,qBACLvT,OAAO2pB,aAAa9sB,KAAK0W,oBACzB1W,KAAK0W,mBAAqB,MAG1B1W,KAAK2W,mBACL3W,KAAK6nB,mBAAmB7nB,KAAK2W,kBAAkB,GAC/C3W,KAAK2W,iBAAmB,MAG5B3W,KAAKyW,oBAAsB,CAC/B,EACA4Z,aAAY,SAACxmB,EAASvB,EAAOqa,GAAO,IAAA2N,EAAAC,EAAAC,EAAAC,EAAAC,EAAA1wB,KAC1B2F,EAAOkE,GAA8B,WAAnB3G,QAAO2G,GACa,QADOymB,EAC1B,QAD0BC,EAC7C1mB,EAAQ2C,mBAAW,IAAA+jB,EAAAA,EAAI1mB,EAAQG,eAAO,IAAAsmB,EAAAA,EAAI,GAC1CzmB,QAAAA,EAAW,GACXwd,GAAS1E,aAAK,EAALA,EAAOgO,iBAAiBhO,SAAa,QAAR6N,EAAL7N,EAAOxK,cAAM,IAAAqY,GAAS,QAATC,EAAbD,EAAelZ,eAAO,IAAAmZ,OAAA,EAAtBA,EAAA/wB,KAAA8wB,EAAyB,+BAAgC,KAEhGvN,UAAU2M,UAAUC,UAAUlqB,GACzB7E,KAAK,WACF4vB,EAAKN,0BACLM,EAAKja,mBAAsC,iBAAVnO,EAAqBA,GAAS,EAC/DooB,EAAK/Z,iBAAmB0Q,EAEpBA,EACAqJ,EAAK7I,mBAAmBR,GAAQ,GAEhCqJ,EAAK5R,UAAU,WAAA,OAAM4R,EAAKjJ,mBAAmB,GAGjDiJ,EAAKha,mBAAqBvT,OAAOypB,WAAW,WACxC8D,EAAKN,0BACLM,EAAK5R,UAAU,WAAA,OAAM4R,EAAKjJ,mBAAmB,EACjD,EAAGF,OAAO1Y,EAAO3K,mBAAqB,IAC1C,GAAE,MACK,SAAA0H,GAAG,OAAIqD,QAAQgB,MAAM,2BAA4BrE,EAAI,EACpE,EACAglB,oBAAmB,SAACC,EAAWxR,GAC3B,GAAKwR,EAAL,CAIA,IAAIC,EAAQD,EAAUrqB,cAAc,gBAChCuqB,EAAUF,EAAUrqB,cAAc,kBAItC,GAAIsqB,EAAO,CACP,IAAIE,GAAyB,IAAf3R,EAAsB,wBAA0B,0BAC1D4R,EAASprB,SAASC,cAAc,QACpCmrB,EAAOvC,UAAYsC,EACnBC,EAAOzO,MAAM0O,SAAW,SACxBJ,EAAM/qB,YAAc,GACpB+qB,EAAM/B,YAAYkC,EACtB,CAEA,GAAIF,EAAS,CACT,IAAII,GAA2B,IAAf9R,EAAuB,0BAA4B,4BAC/D+R,EAAWvrB,SAASC,cAAc,QACtCsrB,EAAS1C,UAAYyC,EACrBC,EAAS5O,MAAM0O,SAAW,SAC1BH,EAAQhrB,YAAc,GACtBgrB,EAAQhC,YAAYqC,EACxB,CAvBA,CAwBJ,EACArS,wBAAuB,WAGnB,IAFA,IAAIsS,EAAarxB,KAAKsxB,IAAIjV,iBAAiB,uCAElC9d,EAAI,EAAGA,EAAI8yB,EAAW9xB,OAAQhB,IAAK,CACxC,IAAIgzB,EAAQF,EAAW9yB,GAAGme,aAAa,mBACnCkC,EAAM5e,KAAKiU,SAASqL,KAAK,SAAAjf,GAAC,OAAIA,EAAEkf,KAAOgS,CAAK,GAE5C3S,GACA5e,KAAK4wB,oBAAoBS,EAAW9yB,GAAIqgB,EAAIS,WAEpD,CACJ,EACAmS,YAAW,SAAC3nB,EAAS4nB,EAAY9O,GAC7B,IAAI3J,EAAYhZ,KAAK0Z,eAErB,GAAKV,GAAcnP,EAAQ0V,IAAOvf,KAAKke,WAAvC,CAKA,IAAIwT,EAAY7nB,EAAQwV,aAAeoS,EAAa,KAAOA,EAC3D5nB,EAAQwV,WAAaqS,EAGrB,IAAIC,EAAoB3xB,KAAKsxB,IAAI9qB,cAC7B,wDAA0DqD,EAAQ0V,GAAK,MAG3Evf,KAAK4wB,oBAAoBe,EAAmBD,GAG1B,OAAdA,GAAsBC,GACtB/E,WAAW,WACP,IAAIgF,EAAWH,EAAa,eAAiB,iBACzChC,EAAMkC,EAAkBnrB,cAAcorB,GAEtCnC,IACAA,EAAIlY,UAAUG,OAAO,gBAChB+X,EAAIoC,YACTpC,EAAIlY,UAAUC,IAAI,gBAClBiY,EAAIlT,iBAAiB,eAAgB,SAASuV,IAC1CrC,EAAIsC,oBAAoB,eAAgBD,GACxCrC,EAAIlY,UAAUG,OAAO,eACzB,GAER,EAAG,IAGP1X,KAAKke,WAAW+J,OAAO,cAAejP,EAAWnP,EAAQ0V,GAAIkS,GAAW,MAAO,SAAU7lB,GACrFqD,QAAQgB,MAAM,0BAA2BrE,EAC7C,EAjCA,CAkCJ,GAEJomB,MAAO,CACH5d,UAAW,CACP6d,QAAO,WACHjyB,KAAK8Z,oBACD9G,GAA+D,mBAAtCA,EAAekf,oBACxClf,EAAekf,mBAAmBlyB,KAAMA,KAAKoU,UAAWvF,EAEhE,EACAsjB,MAAM,GAEV7d,YAAW,WAAKtU,KAAK8Z,mBAAqB,EAC1CvF,2BAA0B,WAAKvU,KAAK8Z,mBAAqB,EACzDvE,eAAc,WAEV,EAEJkB,mBAAkB,WAAG,IAAA2b,EAAApyB,KACjBA,KAAK8e,UAAU,WAAA,OAAMsT,EAAK3K,mBAAmB,EACjD,EACAtR,mBAAkB,SAACkc,GAEXryB,KAAKgV,YACLhV,KAAKgV,UAAUwN,MAAMC,QAAU4P,EAAS,OAAUryB,KAAKiV,oBAAsB,GAAK,QAIlFjV,KAAKyT,gBACLzT,KAAKyT,cAAc+O,MAAMC,QAAU4P,EAAS,OAAS,IAIrDryB,KAAKwT,eACLxT,KAAKwT,aAAa8O,SAAW+P,EACzBA,IACAryB,KAAKwT,aAAalI,YAAc,IAG5C,GAEJgnB,QAAO,WAAG,IAAAC,EAAAvyB,KACNe,kBAAAjD,eAAAuC,EAAC,SAAAmyB,IAAA,OAAA10B,eAAAsC,EAAA,SAAAqyB,GAAA,cAAAA,EAAAt0B,GAAA,KAAA,EAAA,OAAAs0B,EAAAt0B,EAAA,EACSo0B,EAAK1U,kBAAiB,KAAA,EACN0U,EAAKlE,iBACNtb,GAAmBC,GAAsD,mBAA7BA,EAAe0f,WAC5E1f,EAAe0f,UAAUH,EAAM1jB,GAGnC0jB,EAAKzT,UAAU,WACXyT,EAAK9K,oBACLxhB,EAAwBssB,EAAKjB,KAC7BiB,EAAKI,oBAAsB9rB,EAAwB0rB,EAAKjB,IAC5D,GAAG,KAAA,EAAA,OAAAmB,EAAArzB,EAAA,GAAA,EAAAozB,EAAA,GAXPzxB,GAcAoC,OAAOoZ,iBAAiB,eAAgBvc,KAAKgX,oBAC7C7T,OAAOoZ,iBAAiB,6BAA8Bvc,KAAKgnB,sBAC/D,EACA4L,cAAa,WACTzvB,OAAO4uB,oBAAoB,eAAgB/xB,KAAKgX,oBAChD7T,OAAO4uB,oBAAoB,6BAA8B/xB,KAAKgnB,uBAE1DhnB,KAAK2yB,sBACL3yB,KAAK2yB,oBAAoBE,aACzB7yB,KAAK2yB,oBAAsB,MAG/B3yB,KAAKowB,0BACLpwB,KAAKigB,WAAU,GAEXjgB,KAAKgU,SACLhU,KAAKgU,OAAOqR,UACZrlB,KAAKgU,OAAS,MAEdhU,KAAKke,YACLle,KAAKke,WAAW2G,OAGhB7R,GAA4D,mBAAnCA,EAAe8f,iBACxC9f,EAAe8f,gBAAgB9yB,KAAM6O,EAE7C,EACA8D,SAAU9D,EAAOzJ,iBAGf2tB,EAAMC,IAAIC,UAAU1f,GAAe2f,MAAMrkB,EAAOsE,oBAMtD,OAJIH,GAAmD,mBAA1BA,EAAemgB,QACxCngB,EAAemgB,OAAOJ,EAAKlkB,GAGxBkkB,CA/kEP,CAFI9jB,QAAQgB,MAAM,6CAHlB,MAFIhB,QAAQgB,MAAM,8CALdhB,QAAQgB,MAAM,sDALdhB,QAAQgB,MAAM,4CALdhB,QAAQgB,MAAM,iCAsmEtB,EAEMmjB,EAAyB,oEAE/B,SAASC,EAAkBzH,EAAS0H,GAChC,IAAM1zB,EAAQgsB,EAAQlP,aAAa4W,GACnC,OAAiB,OAAV1zB,GAA4B,KAAVA,EAAe,KAAOA,CACnD,CAuBA,SAAS2zB,EAAmB3H,EAAS0H,EAAeE,GAChD,IAAMC,EAAWJ,EAAkBzH,EAAS0H,GAC5C,IAAKG,EACD,OAAO,KAGX,IACI,OAAO9jB,KAAKC,MAAM6jB,EACtB,CAAE,MAAOxjB,GAEL,OADAhB,QAAQgB,MAAM,mBAAqBujB,EAAc,SAAUvjB,GACpD,IACX,CACJ,CAEA,SAASyjB,EAA8B9H,EAAS/b,GAAS,IAAA8jB,EAAAC,EAC/CC,EAAWhkB,GAAW,CAAC,EAE7B,GAAI+b,EAAQkI,aAAa,gDAA8E,IAA7BD,EAASE,gBAC/E,OAAO,KAGX,IAAM5gB,EAAqBkgB,EAAkBzH,EAAS,yCACtD,IAAKzY,EACD,OAAO,KAGX,IAAMtE,EAAS,CACXqE,cAAemgB,EAAkBzH,EAAS,oCAC1CzY,mBAAoBA,EACpBC,6BAA8BigB,EAAkBzH,EAAS,+CACzDvY,qBAAsBggB,EAAkBzH,EAAS,2CACjDtY,0BAA2B+f,EAAkBzH,EAAS,iDACtD2C,2BAA4B8E,EAAkBzH,EAAS,iDACvD3X,SAA0F,QAAlF0f,EAAEJ,EAAmB3H,EAAS,4BAA6B,+BAAuB,IAAA+H,EAAAA,OAAIhjB,EAC9FuE,SAAUme,EAAkBzH,EAAS,yBACrCmE,yBAA0BsD,EAAkBzH,EAAS,gDACrDoE,kCAAmCqD,EAAkBzH,EAAS,yDAC9DxW,aAAcie,EAAkBzH,EAAS,mCACzC6C,oBAAqB4E,EAAkBzH,EAAS,0CAChD9S,kBAAmBua,EAAkBzH,EAAS,wCAC9C7Q,kBAAmBsY,EAAkBzH,EAAS,wCAC9CgD,kBAAmByE,EAAkBzH,EAAS,uCAC9C3P,wBAAyBoX,EAAkBzH,EAAS,8CACpDvX,kBAAuH,QAAtGuf,EAAEL,EAAmB3H,EAAS,sCAAuC,yCAAiC,IAAAgI,EAAAA,OAAIjjB,EAC3HqO,cAAeqU,EAAkBzH,EAAS,mCAC1CjoB,UAAW0vB,EAAkBzH,EAAS,+BACtChoB,eAAgByvB,EAAkBzH,EAAS,oCAC3C7nB,UAAWsvB,EAAkBzH,EAAS,+BACtC5nB,YAAaqvB,EAAkBzH,EAAS,kCAGtCoI,EAAoB,CACtBpf,eAAgB,mCAChBO,oBAAqB,0CACrB+B,wBAAyB,6CACzBlB,mBAAoB,yCAUxB,OAPApX,OAAO0T,KAAK0hB,GAAmB/sB,QAAQ,SAAAyC,GACnC,IAAMsT,EAhFd,SAAoCpd,GAChC,GAAIA,QACA,OAAO,KAGX,GAAqB,kBAAVA,EACP,OAAOA,EAGX,IAAMwI,EAAaoc,OAAO5kB,GAAO6F,OAAOyD,cACxC,MAAmB,SAAfd,GAIe,UAAfA,GAIG,IACX,CA6DuB6rB,CAA2BZ,EAAkBzH,EAASoI,EAAkBtqB,KACxE,OAAXsT,IACAnO,EAAOnF,GAAOsT,EAEtB,GAEOzM,EAAc1B,EACzB,CAEA,SAASqlB,EAAuBtI,EAAS/b,GACrC,IAAMskB,EAAaZ,EAAmB3H,EAAS,0BAA2B,sBACpEwI,EAAkBV,EAA8B9H,EAAS/b,GAE/D,OAAKskB,GAAeC,EAIbx1B,OAAOyJ,OAAO,CAAC,EAAG8rB,GAAc,CAAC,EAAGC,GAAmB,CAAC,GAHpD,IAIf,CAEA,SAASC,EAAsBzI,GAC3B,IAAKA,GAAqD,SAA1CA,EAAQ0I,QAAQC,sBAC5B,OAAO3I,GAAUA,EAAQ4I,iBAA0B,KAGvD,IAAM3lB,EAASqlB,EAAuBtI,GACtC,IAAK/c,EACD,OAAO,KAGX,IAAMkkB,EAAMxgB,EAAW1D,GACvB,OAAKkkB,GAILnH,EAAQ0I,QAAQC,sBAAwB,OACxC3I,EAAQ4I,gBAAkBzB,EAEnBA,GANI,IAOf,CAEA,SAAS0B,EAA0BvuB,GAC1BA,GAAyC,mBAA1BA,EAAKmW,mBAIG,mBAAjBnW,EAAKK,SAA0BL,EAAKK,QAAQ6sB,IACnDiB,EAAsBnuB,GAG1BA,EAAKmW,iBAAiB+W,GAAwBnsB,QAAQotB,GAC1D,CAEA,SAASK,KACLD,EAA0B5uB,UAEM,oBAArBiB,mBAIM,IAAIA,iBAAiB,SAAAE,GAClCA,EAAUC,QAAQ,SAAAC,GACdA,EAASC,WAAWF,QAAQ,SAAAL,GACpBA,GAA0B,IAAlBA,EAAKP,UACbouB,EAA0B7tB,EAElC,EACJ,EACJ,GAESQ,QAAQvB,SAASsU,KAAM,CAC5B9S,WAAW,EACXC,SAAS,GAEjB,CAQA,MAN4B,YAAxBzB,SAAS8uB,WACT9uB,SAAS0W,iBAAiB,mBAAoBmY,EAAyB,CAAEE,MAAM,IAE/EF,IAGG,CACHniB,WAAYA,EACZ8hB,sBAAuBA,EACvBH,uBAAwBA,EAEhC,CAp5F2B,GAu5F3BruB,SAAS0W,iBAAiB,QAAS,SAAUxe,GACzC,IAAM0xB,EAAM1xB,EAAEoa,OAAOb,QAAQ,uBAC7B,GAAKmY,EAAL,CAGA,IAAM7gB,EAAU6gB,EAAI/S,aAAa,iBAC3B5N,EAASF,EAAU/I,SAASkJ,eAAeH,GAAW,KAC5D,GAAKE,EAAL,CAIA,IAAMnG,EAAO9C,SAASC,cAAc,KACpC6C,EAAKksB,SAAW,SAAWjmB,EAAU,OACrCjG,EAAK0E,KAAOyB,EAAOgmB,UAAU,aAC7BnsB,EAAKsP,OAJL,MAFIhJ,QAAQgB,MAAM,0BAA2BrB,EAJ7C,CAWJ,GAGA/I,SAAS0W,iBAAiB,QAAS,SAAUxe,GACzC,IAAM4K,EAAO5K,EAAEoa,OAAOb,QAAQ,sBAC9B,GAAK3O,EAAL,CAIA,IAAMkoB,EAAYloB,EAAK2O,QAAQ,8BACzByd,EAAMlE,aAAS,EAATA,EAAWrqB,cAAc,OACrC,GAAKuuB,EAAL,CAIA,IAAM9mB,EAAM8mB,EAAI9mB,IACXA,GAAQA,EAAI8O,WAAW,WAI5Bhf,EAAEoZ,iBAEF8C,MAAMhM,GACDnN,KAAK,SAAUk0B,GAAO,OAAOA,EAAInM,MAAQ,GACzC/nB,KAAK,SAAU+nB,GACZ,IAAMtjB,EAAMyjB,IAAIC,gBAAgBJ,GAC1BzpB,EAAIyG,SAASC,cAAc,KACjC1G,EAAEiO,KAAO9H,EACTnG,EAAEy1B,SAAWlsB,EAAK+T,aAAa,aAAe,sBAC9C7W,SAASsU,KAAK4U,YAAY3vB,GAC1BA,EAAE6Y,QACFpS,SAASsU,KAAK8a,YAAY71B,GAC1BwtB,WAAW,WAAc5D,IAAIG,gBAAgB5jB,EAAM,EAAG,IAC1D,GAAE,MACK,SAAUqG,GAAOqD,QAAQgB,MAAM,4BAA6BrE,EAAM,GArB7E,CANA,CA4BJ","file":"ai-chat.min.js","sourcesContent":["window.coreAIChatManager = function () {\n\n // Defaults (can be overridden by instanceConfig)\n var defaultConfig = {\n // UI defaults for generated media\n generatedImageAltText: 'Generated Image',\n generatedImageMaxWidth: 400,\n downloadImageTitle: 'Download image',\n downloadChartTitle: 'Download chart as image',\n downloadChartButtonText: 'Download',\n userLabel: 'You',\n assistantLabel: 'Assistant',\n thumbsUpTitle: 'Thumbs up',\n thumbsDownTitle: 'Thumbs down',\n copyTitle: 'Click here to copy response to clipboard.',\n copiedTitle: 'Response copied to clipboard.',\n codeCopiedText: 'Copied!',\n copyResetDelayMs: 2000,\n widget: {\n chatWidgetContainer: null,\n chatWidgetStateName: null,\n chatHistorySection: null,\n showHistoryButton: null,\n closeHistoryButton: null,\n newChatButton: null,\n toggleButtonSelector: null,\n resetSizeButtonSelector: null,\n dragHandleSelector: '.ai-chat-widget-header',\n enableDragging: true,\n enableResizing: true,\n persistLayout: true,\n defaultWidth: null,\n defaultHeight: null,\n minWidth: 320,\n minHeight: 420\n },\n messageTemplate: `\n
\n \n
\n
\n \n {{ notification.content }}\n \n
\n
\n \n
\n
\n
\n `,\n indicatorTemplate: `\n
\n
\n \n Assistant\n
\n
\n `\n };\n\n // Sanitize URLs to prevent javascript: protocol injection.\n function sanitizeUrl(url) {\n if (!url) return '';\n var trimmed = url.trim();\n if (/^javascript:/i.test(trimmed) || /^vbscript:/i.test(trimmed) || /^data:text\\/html/i.test(trimmed)) {\n return '';\n }\n return url;\n }\n\n // Safely HTML-encode a string using the DOM (avoids regex-based HTML filtering).\n function escapeHtmlEntities(text) {\n var span = document.createElement('span');\n span.textContent = text;\n return span.innerHTML;\n }\n\n function containsFontAwesomePlaceholders(root) {\n if (!root || root.nodeType !== 1) {\n return false;\n }\n\n var selector = 'i[class*=\"fa-\"],i.fa,i.fas,i.far,i.fab';\n if (typeof root.matches === 'function' && root.matches(selector)) {\n return true;\n }\n\n return typeof root.querySelector === 'function' && !!root.querySelector(selector);\n }\n\n function refreshFontAwesomeIcons(root) {\n var fontAwesome = window.FontAwesome;\n if (!containsFontAwesomePlaceholders(root) || !fontAwesome || !fontAwesome.dom || typeof fontAwesome.dom.i2svg !== 'function') {\n return;\n }\n\n fontAwesome.dom.i2svg({ node: root });\n }\n\n function observeFontAwesomeIcons(root) {\n if (!root || typeof MutationObserver === 'undefined') {\n return null;\n }\n\n var observer = new MutationObserver(function (mutations) {\n mutations.forEach(function (mutation) {\n mutation.addedNodes.forEach(function (node) {\n refreshFontAwesomeIcons(node);\n });\n });\n });\n\n observer.observe(root, {\n childList: true,\n subtree: true\n });\n\n return observer;\n }\n\n function parsePixelValue(value) {\n if (typeof value === 'number' && Number.isFinite(value)) {\n return value;\n }\n\n if (typeof value !== 'string') {\n return null;\n }\n\n var parsed = parseFloat(value);\n return Number.isFinite(parsed) ? parsed : null;\n }\n\n function clamp(value, min, max) {\n return Math.min(Math.max(value, min), max);\n }\n\n function normalizeReference(reference) {\n if (!reference || typeof reference !== 'object') {\n return null;\n }\n\n const normalized = Object.assign({}, reference);\n normalized.index = normalized.index ?? normalized.Index ?? 0;\n normalized.text = normalized.text ?? normalized.Text ?? null;\n normalized.title = normalized.title ?? normalized.Title ?? null;\n normalized.link = sanitizeUrl(normalized.link ?? normalized.Link ?? null);\n normalized.referenceType = normalized.referenceType ?? normalized.ReferenceType ?? null;\n normalized.isGenerated = (normalized.isGenerated ?? normalized.IsGenerated) === true;\n\n return normalized;\n }\n\n function isDownloadCitationReference(reference) {\n if (!reference || typeof reference !== 'object') {\n return false;\n }\n\n if (typeof reference.referenceType === 'string' && reference.referenceType.toLowerCase() === 'document') {\n return true;\n }\n\n if (typeof reference.link === 'string' && /\\/ai\\/documents\\/.+\\/download(?:$|\\?)/i.test(reference.link)) {\n return true;\n }\n\n return false;\n }\n\n function normalizeReferences(references) {\n if (!references || typeof references !== 'object') {\n return {};\n }\n\n const normalized = {};\n\n for (const [key, value] of Object.entries(references)) {\n normalized[key] = normalizeReference(value) ?? {};\n }\n\n return normalized;\n }\n\n function getCitationLabel(reference, key) {\n return reference.title || reference.text || key;\n }\n\n function buildCitationDisplay(content, references) {\n let processedContent = (content || '').trim();\n const messageReferences = normalizeReferences(references);\n const referenceEntries = Object.entries(messageReferences);\n\n if (!referenceEntries.length) {\n return { content: processedContent, citations: [] };\n }\n\n const citedRefs = referenceEntries.filter(([key]) => processedContent.includes(key));\n const generatedRefs = referenceEntries.filter(([key, value]) => value.isGenerated && !processedContent.includes(key));\n\n if (!citedRefs.length && !generatedRefs.length) {\n return { content: processedContent, citations: [] };\n }\n\n citedRefs.sort(([, a], [, b]) => a.index - b.index);\n generatedRefs.sort(([, a], [, b]) => a.index - b.index);\n\n const citations = [];\n let displayIndex = 1;\n\n for (const [key, value] of citedRefs) {\n const placeholder = `__CITE_${displayIndex}_${value.index || displayIndex}__`;\n processedContent = processedContent.replaceAll(key, placeholder);\n citations.push({\n referenceKey: key,\n displayIndex: displayIndex,\n label: getCitationLabel(value, key),\n link: value.link || null,\n isDownload: isDownloadCitationReference(value),\n placeholder: placeholder,\n });\n\n displayIndex++;\n }\n\n for (const citation of citations) {\n processedContent = processedContent.replaceAll(citation.placeholder, `${citation.displayIndex}`);\n }\n\n processedContent = processedContent.replaceAll('
', ',');\n\n // Generated files (such as exported tabular data) are always offered as a download even when\n // the model does not cite them inline, so the user never loses access to the produced file.\n for (const [key, value] of generatedRefs) {\n citations.push({\n referenceKey: key,\n displayIndex: displayIndex,\n label: getCitationLabel(value, key),\n link: value.link || null,\n isDownload: true,\n placeholder: null,\n });\n\n displayIndex++;\n }\n\n return {\n content: processedContent,\n citations: citations.map(({ placeholder, ...citation }) => citation),\n };\n }\n\n function buildCopyContent(content, citations) {\n let copyContent = (content || '').trim();\n\n if (!copyContent || !Array.isArray(citations) || citations.length === 0) {\n return copyContent;\n }\n\n for (const citation of citations) {\n copyContent = copyContent.replaceAll(citation.referenceKey, `[${citation.displayIndex}]`);\n }\n\n copyContent += '\\n\\nReferences:\\n';\n\n for (const citation of citations) {\n copyContent += `${citation.displayIndex}. ${citation.label}`;\n\n if (citation.link) {\n copyContent += ` - ${citation.link}`;\n }\n\n copyContent += '\\n';\n }\n\n return copyContent.trimEnd();\n }\n\n function updateMessagePresentation(message, references) {\n const messageReferences = normalizeReferences(references ?? message.references);\n const rawContent = typeof message.rawContent === 'string'\n ? message.rawContent\n : typeof message.content === 'string'\n ? message.content\n : '';\n const citationDisplay = buildCitationDisplay(rawContent, messageReferences);\n\n message.rawContent = rawContent;\n message.content = rawContent;\n message.displayContent = citationDisplay.content;\n message.references = messageReferences;\n message.citationReferences = citationDisplay.citations;\n message.copyContent = buildCopyContent(rawContent, citationDisplay.citations);\n message.htmlContent = parseMarkdownContent(citationDisplay.content, message);\n\n return message;\n }\n\n const renderer = new marked.Renderer();\n\n // Modify the link rendering to open in a new tab\n renderer.link = function (data) {\n var href = sanitizeUrl(data.href);\n if (!href) return data.text || '';\n return `${data.text}`;\n };\n\n // Custom code block renderer with highlight.js integration and copy button.\n renderer.code = function (data) {\n var code = data.text || '';\n var lang = (data.lang || '').trim();\n var highlighted = code;\n\n if (typeof hljs !== 'undefined') {\n if (lang && hljs.getLanguage(lang)) {\n try {\n highlighted = hljs.highlight(code, { language: lang }).value;\n } catch (_) { }\n } else {\n try {\n highlighted = hljs.highlightAuto(code).value;\n } catch (_) { }\n }\n } else {\n highlighted = escapeHtmlEntities(code);\n }\n\n var langDisplay = lang ? escapeHtmlEntities(lang) : 'code';\n return `
${langDisplay}
${highlighted}
`;\n };\n\n // Custom image renderer for generated images with thumbnail styling and download button.\n // Handles both URL and data-URI sources (data URIs are converted to blobs for download).\n renderer.image = function (data) {\n const src = sanitizeUrl(data.href);\n if (!src) return '';\n const alt = data.text || defaultConfig.generatedImageAltText;\n const maxWidth = defaultConfig.generatedImageMaxWidth;\n return `
\n \"${alt}\"\n
\n \n \n \n
\n
`;\n };\n\n // Chart counter for unique IDs\n let chartCounter = 0;\n\n // Collector for charts discovered during marked parsing.\n let _pendingCharts = [];\n\n // Global chart config map: any page (e.g., Chat Interactions) that uses\n // the shared marked instance can call window.renderPendingCharts() after\n // its DOM update to render charts it didn't create itself.\n window.__chartConfigs = window.__chartConfigs || {};\n\n function createChartHtml(chartId) {\n return `
`\n + ``\n + `
`\n + `
`\n + ``\n + `
`;\n }\n\n // Register [chart:{...json...}] as a native marked block extension so the\n // markdown parser handles chart markers inline with surrounding text.\n marked.use({\n extensions: [{\n name: 'chart',\n level: 'block',\n start(src) {\n const idx = src.indexOf('[chart:');\n return idx >= 0 ? idx : undefined;\n },\n tokenizer(src) {\n const extracted = tryExtractChartMarker(src);\n if (!extracted || extracted.startIndex !== 0) {\n return undefined;\n }\n\n const chartId = `chat_chart_${++chartCounter}`;\n\n return {\n type: 'chart',\n raw: src.substring(0, extracted.endIndex),\n chartId: chartId,\n json: extracted.json,\n };\n },\n renderer(token) {\n _pendingCharts.push({ chartId: token.chartId, config: token.json });\n window.__chartConfigs[token.chartId] = token.json;\n return createChartHtml(token.chartId);\n }\n }]\n });\n\n // Extract a [chart:{...json...}] marker. This avoids regex issues with nested brackets.\n function tryExtractChartMarker(text) {\n const token = '[chart:';\n const start = text.indexOf(token);\n if (start < 0) {\n return null;\n }\n\n // Find JSON object boundary by balancing braces\n const jsonStart = start + token.length;\n let i = jsonStart;\n while (i < text.length && (text[i] === ' ' || text[i] === '\\n' || text[i] === '\\r' || text[i] === '\\t')) {\n i++;\n }\n\n if (i >= text.length || text[i] !== '{') {\n return null;\n }\n\n let depth = 0;\n let inString = false;\n let escape = false;\n\n for (; i < text.length; i++) {\n const ch = text[i];\n\n if (inString) {\n if (escape) {\n escape = false;\n continue;\n }\n if (ch === '\\\\') {\n escape = true;\n continue;\n }\n if (ch === '\"') {\n inString = false;\n }\n continue;\n }\n\n if (ch === '\"') {\n inString = true;\n continue;\n }\n\n if (ch === '{') {\n depth++;\n } else if (ch === '}') {\n depth--;\n if (depth === 0) {\n const jsonEnd = i;\n // Expect closing bracket after JSON\n const closeBracketIndex = text.indexOf(']', jsonEnd + 1);\n if (closeBracketIndex < 0) {\n return null;\n }\n\n const json = text.substring(jsonStart, jsonEnd + 1).trim();\n return {\n startIndex: start,\n endIndex: closeBracketIndex + 1,\n json: json\n };\n }\n }\n }\n\n return null;\n }\n\n function renderChartsInMessage(message) {\n if (!message || !message._pendingCharts || !message._pendingCharts.length) {\n return;\n }\n\n // Copy and clear pending charts immediately to prevent duplicate renders.\n const charts = [...message._pendingCharts];\n message._pendingCharts = [];\n\n // Defer to requestAnimationFrame so the browser has fully laid out the\n // canvas elements before Chart.js reads their dimensions.\n requestAnimationFrame(() => {\n for (const c of charts) {\n renderChartOnCanvas(c.chartId, c.config);\n }\n });\n }\n\n function renderChartOnCanvas(chartId, config) {\n const canvas = document.getElementById(chartId);\n if (!canvas) {\n return false;\n }\n\n if (typeof Chart === 'undefined') {\n console.warn('Chart.js is not loaded. To render interactive charts, include the Chart.js library on the page (e.g., ).');\n return false;\n }\n\n // When the canvas is inside a hidden container (e.g., a widget panel with\n // display:none), it has zero dimensions and Chart.js cannot render correctly.\n // Keep the config in __chartConfigs so renderPendingCharts() can retry later\n // once the container becomes visible.\n if (canvas.offsetParent === null) {\n window.__chartConfigs[chartId] = config;\n return false;\n }\n\n try {\n if (canvas._chartInstance) {\n canvas._chartInstance.destroy();\n }\n\n const cfg = typeof config === 'string' ? JSON.parse(config) : config;\n cfg.options ??= {};\n cfg.options.responsive = true;\n cfg.options.maintainAspectRatio = true;\n cfg.options.aspectRatio ??= 4 / 3;\n\n canvas._chartInstance = new Chart(canvas, cfg);\n delete window.__chartConfigs[chartId];\n return true;\n } catch (e) {\n console.error('Error creating chart:', e);\n return false;\n }\n }\n\n // Global function: renders any chart canvases whose configs are in the\n // global __chartConfigs map. Called by pages (e.g., Chat Interactions)\n // that share the marked instance but have their own rendering pipeline.\n window.renderPendingCharts = function () {\n if (typeof Chart === 'undefined') {\n return;\n }\n\n const configs = window.__chartConfigs;\n if (!configs) {\n return;\n }\n\n requestAnimationFrame(() => {\n for (const chartId of Object.keys(configs)) {\n renderChartOnCanvas(chartId, configs[chartId]);\n }\n });\n };\n\n // Parse markdown content via marked (which natively handles [chart:...] markers\n // through the registered extension) and collect pending chart configs for later\n // Chart.js rendering.\n function parseMarkdownContent(content, message) {\n _pendingCharts = [];\n const html = marked.parse(content, { renderer });\n message._pendingCharts = _pendingCharts.length > 0 ? [..._pendingCharts] : [];\n return DOMPurify.sanitize(html, { ADD_TAGS: ['canvas'], ADD_ATTR: ['target'] });\n }\n\n function compactObject(source) {\n if (!source || typeof source !== 'object') {\n return {};\n }\n\n return Object.fromEntries(\n Object.entries(source).filter(([, value]) => value !== undefined)\n );\n }\n\n function resolveIndicatorTemplate(template, assistantLabel) {\n if (!template) {\n return template;\n }\n\n const encodedAssistantLabel = escapeHtmlEntities(assistantLabel || 'Assistant');\n return template.replace(/\\{\\{\\s*assistantLabel\\s*\\}\\}/g, encodedAssistantLabel);\n }\n\n const initialize = (instanceConfig) => {\n const normalizedInstanceConfig = compactObject(instanceConfig);\n const normalizedWidgetConfig = compactObject(normalizedInstanceConfig.widget);\n const config = Object.assign({}, defaultConfig, normalizedInstanceConfig);\n config.widget = Object.assign({}, defaultConfig.widget || {}, normalizedWidgetConfig);\n config.indicatorTemplate = resolveIndicatorTemplate(config.indicatorTemplate, config.assistantLabel);\n const hasWidgetConfig = !!(normalizedWidgetConfig.chatWidgetContainer && normalizedWidgetConfig.chatWidgetStateName);\n const widgetBehavior = window.coreAIChatWidgetBehavior || null;\n // Keep defaultConfig in sync so renderers use overridden values\n defaultConfig = config;\n\n if (!config.signalRHubUrl) {\n console.error('The signalRHubUrl is required.');\n return;\n }\n\n if (!config.appElementSelector) {\n console.error('The appElementSelector is required.');\n return;\n }\n\n if (!config.chatContainerElementSelector) {\n console.error('The chatContainerElementSelector is required.');\n return;\n }\n\n if (!config.inputElementSelector) {\n console.error('The inputElementSelector is required.');\n return;\n }\n\n if (!config.sendButtonElementSelector) {\n console.error('The sendButtonElementSelector is required.');\n return;\n }\n\n const appDefinition = {\n data() {\n return {\n inputElement: null,\n buttonElement: null,\n chatContainer: null,\n placeholder: null,\n isSessionStarted: false,\n isPlaceholderVisible: true,\n isStreaming: false,\n isNavigatingAway: false,\n autoScroll: true,\n stream: null,\n messages: [],\n notifications: [],\n prompt: '',\n documents: config.existingDocuments || [],\n isUploading: false,\n isDocumentOperationPending: false,\n documentOperationQueue: null,\n uploadErrors: [],\n isDragOver: false,\n documentBar: null,\n metricsEnabled: !!config.metricsEnabled,\n userLabel: config.userLabel,\n assistantLabel: config.assistantLabel,\n thumbsUpTitle: config.thumbsUpTitle,\n thumbsDownTitle: config.thumbsDownTitle,\n copyTitle: config.copyTitle,\n copiedTitle: config.copiedTitle,\n isRecording: false,\n mediaRecorder: null,\n preRecordingPrompt: '',\n micButton: null,\n speechToTextEnabled: config.chatMode === 'AudioInput' || config.chatMode === 'Conversation',\n textToSpeechEnabled: config.chatMode === 'Conversation' || !!config.textToSpeechEnabled,\n ttsVoiceName: config.ttsVoiceName || null,\n audioChunks: [],\n audioPlayQueue: [],\n isPlayingAudio: false,\n currentAudioElement: null,\n currentAudioUrl: null,\n ttsButton: null,\n ttsPlayingMessageIndex: -1,\n ttsAudioCache: {},\n ttsInstanceId: 'ai-chat-' + Math.random().toString(36).slice(2),\n singleResponseMode: !!config.singleResponseMode,\n conversationModeEnabled: config.chatMode === 'Conversation',\n conversationButton: null,\n isConversationMode: false,\n notificationDismissTimers: {},\n pendingSessionPromise: null,\n pendingSessionResolver: null,\n pendingSessionRejector: null,\n pendingSessionTimeoutId: null,\n copiedMessageIndex: -1,\n copyResetTimeoutId: null,\n activeCopyButton: null,\n };\n },\n computed: {\n lastAssistantIndex() {\n for (var i = this.messages.length - 1; i >= 0; i--) {\n if (this.messages[i].role === 'assistant') {\n return i;\n }\n }\n return -1;\n }\n },\n methods: {\n handleBeforeUnload() {\n this.isNavigatingAway = true;\n },\n handleDragOver(e) {\n if (!config.sessionDocumentsEnabled) return;\n e.preventDefault();\n e.stopPropagation();\n this.isDragOver = true;\n var inputArea = this.inputElement ? this.inputElement.closest('.ai-admin-widget-input, .text-bg-light') : null;\n if (inputArea) inputArea.classList.add('ai-chat-drag-over');\n },\n handleDragLeave(e) {\n if (!config.sessionDocumentsEnabled) return;\n e.preventDefault();\n e.stopPropagation();\n this.isDragOver = false;\n var inputArea = this.inputElement ? this.inputElement.closest('.ai-admin-widget-input, .text-bg-light') : null;\n if (inputArea) inputArea.classList.remove('ai-chat-drag-over');\n },\n handleDrop(e) {\n if (!config.sessionDocumentsEnabled) return;\n e.preventDefault();\n e.stopPropagation();\n this.isDragOver = false;\n var inputArea = this.inputElement ? this.inputElement.closest('.ai-admin-widget-input, .text-bg-light') : null;\n if (inputArea) inputArea.classList.remove('ai-chat-drag-over');\n if (e.dataTransfer && e.dataTransfer.files && e.dataTransfer.files.length > 0) {\n this.uploadFiles(Array.from(e.dataTransfer.files));\n }\n },\n triggerFileInput() {\n if (!config.sessionDocumentsEnabled || this.isDocumentOperationPending) return;\n var fileInput = document.getElementById('ai-chat-doc-input');\n if (fileInput) fileInput.click();\n },\n handleFileInputChange(e) {\n var files = e.target.files ? Array.from(e.target.files) : [];\n if (files && files.length > 0) {\n this.uploadFiles(files);\n }\n e.target.value = '';\n },\n queueDocumentOperation(operation) {\n var self = this;\n var previousOperation = this.documentOperationQueue || Promise.resolve();\n var nextOperation = previousOperation\n .catch(function () { })\n .then(async function () {\n self.isDocumentOperationPending = true;\n try {\n return await operation();\n } finally {\n self.isDocumentOperationPending = false;\n }\n });\n\n this.documentOperationQueue = nextOperation.finally(function () {\n if (self.documentOperationQueue === nextOperation) {\n self.documentOperationQueue = null;\n }\n });\n\n return this.documentOperationQueue;\n },\n async uploadFiles(files) {\n if (!config.uploadDocumentUrl) return;\n\n var filesToUpload = Array.isArray(files) ? files.slice() : Array.from(files || []);\n if (filesToUpload.length === 0) return;\n\n return this.queueDocumentOperation(async () => {\n var sessionId = this.getSessionId();\n var profileId = this.getProfileId();\n\n if (!sessionId) {\n try {\n sessionId = await this.ensureSessionForDocuments(profileId);\n } catch (err) {\n console.error('Failed to create a chat session for document upload:', err);\n this.uploadErrors = [{ fileName: '', error: 'Could not create a chat session for the upload.' }];\n this.renderDocumentBar();\n return;\n }\n }\n\n if (!sessionId) {\n console.warn('Cannot upload documents without a session or profile.');\n this.uploadErrors = [{ fileName: '', error: 'Could not create a chat session for the upload.' }];\n this.renderDocumentBar();\n return;\n }\n\n this.isUploading = true;\n this.uploadErrors = [];\n this.renderDocumentBar();\n try {\n var formData = new FormData();\n formData.append('sessionId', sessionId);\n for (var i = 0; i < filesToUpload.length; i++) {\n formData.append('files', filesToUpload[i]);\n }\n\n var response = await fetch(config.uploadDocumentUrl, {\n method: 'POST',\n body: formData\n });\n\n if (!response.ok) {\n var errorText = await response.text();\n var uploadError = this.extractReadableErrorMessage(errorText, 'Upload failed. Please try again.');\n console.error('Upload failed:', errorText);\n this.uploadErrors = [{ fileName: '', error: uploadError }];\n return;\n }\n\n var result = await response.json();\n\n if (result.sessionId && result.sessionId !== this.getSessionId()) {\n this.initializeSession(result.sessionId);\n }\n\n if (Array.isArray(result.documents)) {\n this.documents = result.documents;\n } else if (result.uploaded && result.uploaded.length > 0) {\n this.documents = this.documents.concat(result.uploaded);\n }\n\n if (result.failed && result.failed.length > 0) {\n this.uploadErrors = result.failed;\n }\n } catch (err) {\n console.error('Upload error:', err);\n this.uploadErrors = [{ fileName: '', error: 'Upload failed. Please try again.' }];\n\n if (this.getSessionId()) {\n this.reloadCurrentSession();\n }\n } finally {\n this.isUploading = false;\n this.renderDocumentBar();\n }\n });\n },\n async removeDocument(doc) {\n if (!config.removeDocumentUrl) return;\n\n return this.queueDocumentOperation(async () => {\n try {\n var sessionId = this.getSessionId();\n var response = await fetch(config.removeDocumentUrl, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ itemId: sessionId, documentId: doc.documentId })\n });\n\n if (response.ok) {\n var result = await response.json();\n\n if (Array.isArray(result.documents)) {\n this.documents = result.documents;\n } else {\n var idx = this.documents.indexOf(doc);\n if (idx > -1) {\n this.documents.splice(idx, 1);\n }\n }\n } else {\n var errorText = await response.text();\n var removeError = this.extractReadableErrorMessage(errorText, 'Failed to remove document. Please try again.');\n console.error('Failed to remove document:', response.status, errorText);\n this.uploadErrors = [{ fileName: doc.fileName || '', error: removeError }];\n if (sessionId) {\n this.reloadCurrentSession();\n }\n this.renderDocumentBar();\n }\n } catch (err) {\n console.error('Remove document error:', err);\n this.uploadErrors = [{ fileName: doc.fileName || '', error: 'Failed to remove document. Please try again.' }];\n if (this.getSessionId()) {\n this.reloadCurrentSession();\n }\n this.renderDocumentBar();\n }\n });\n },\n formatFileSize(bytes) {\n if (bytes < 1024) return bytes + ' B';\n if (bytes < 1024 * 1024) return (bytes / 1024).toFixed(1) + ' KB';\n return (bytes / (1024 * 1024)).toFixed(1) + ' MB';\n },\n renderDocumentBar() {\n if (!this.documentBar) return;\n\n if (!config.sessionDocumentsEnabled) {\n this.documentBar.classList.add('d-none');\n return;\n }\n\n this.documentBar.classList.remove('d-none');\n\n var html = '
';\n html += '
';\n\n for (var i = 0; i < this.documents.length; i++) {\n var doc = this.documents[i];\n var name = doc.fileName || 'Document';\n if (name.length > 20) name = name.substring(0, 17) + '...';\n html += '';\n html += ' ';\n html += this.escapeHtml(name);\n html += ' ';\n html += '';\n }\n\n for (var m = 0; m < this.uploadErrors.length; m++) {\n var failedItem = this.uploadErrors[m];\n var failedName = failedItem.fileName || 'File';\n var errorMsg = failedItem.error || 'Upload failed';\n if (failedName.length > 15) failedName = failedName.substring(0, 12) + '...';\n html += '';\n html += ' ';\n html += this.escapeHtml(failedName);\n html += ' ';\n html += '';\n }\n\n if (this.isUploading) {\n html += '';\n html += ' Uploading...';\n html += '';\n }\n\n html += '';\n html += '
';\n if (config.supportedExtensionsText) {\n html += '
Supported formats: ' + this.escapeHtml(config.supportedExtensionsText) + '
';\n }\n\n html += '
';\n\n this.documentBar.replaceChildren(DOMPurify.sanitize(html, { RETURN_DOM_FRAGMENT: true }));\n\n // Bind remove handlers\n var self = this;\n var closeButtons = this.documentBar.querySelectorAll('[data-doc-index]');\n for (var j = 0; j < closeButtons.length; j++) {\n closeButtons[j].addEventListener('click', (function (idx) {\n return function (e) {\n e.preventDefault();\n e.stopPropagation();\n if (self.isDocumentOperationPending) {\n return;\n }\n\n var docToRemove = self.documents[idx];\n if (docToRemove) self.removeDocument(docToRemove);\n };\n })(parseInt(closeButtons[j].getAttribute('data-doc-index'))));\n }\n\n // Bind error dismiss handlers\n var errorCloseButtons = this.documentBar.querySelectorAll('[data-error-index]');\n for (var n = 0; n < errorCloseButtons.length; n++) {\n errorCloseButtons[n].addEventListener('click', (function (idx) {\n return function (e) {\n e.preventDefault();\n e.stopPropagation();\n self.uploadErrors.splice(idx, 1);\n self.renderDocumentBar();\n };\n })(parseInt(errorCloseButtons[n].getAttribute('data-error-index'))));\n }\n\n // Bind add button\n var addBtn = this.documentBar.querySelector('.ai-chat-doc-add-btn');\n if (addBtn) {\n addBtn.addEventListener('click', function (e) {\n e.preventDefault();\n if (self.isDocumentOperationPending) {\n return;\n }\n self.triggerFileInput();\n });\n }\n },\n escapeHtml(text) {\n var div = document.createElement('div');\n div.textContent = text;\n return div.innerHTML;\n },\n extractReadableErrorMessage(errorText, fallbackMessage) {\n if (!errorText || typeof errorText !== 'string') {\n return fallbackMessage;\n }\n\n var trimmed = errorText.trim();\n if (!trimmed) {\n return fallbackMessage;\n }\n\n if (trimmed.startsWith('{') || trimmed.startsWith('[')) {\n try {\n var parsed = JSON.parse(trimmed);\n var message = parsed?.error || parsed?.message || parsed?.title || parsed?.detail;\n return typeof message === 'string' && message.trim()\n ? message.trim()\n : fallbackMessage;\n } catch (err) {\n return fallbackMessage;\n }\n }\n\n if (/<[^>]+>/.test(trimmed)) {\n return fallbackMessage;\n }\n\n return trimmed;\n },\n normalizeAssistantAppearance(appearance) {\n if (!appearance) {\n return null;\n }\n\n var label = typeof appearance.label === 'string' ? appearance.label.trim() : '';\n var icon = typeof appearance.icon === 'string' ? appearance.icon.trim() : '';\n var cssClass = typeof appearance.cssClass === 'string' ? appearance.cssClass.trim() : '';\n var disableStreamingAnimation = !!appearance.disableStreamingAnimation;\n\n if (!label && !icon && !cssClass && !disableStreamingAnimation) {\n return null;\n }\n\n return {\n label: label,\n icon: icon,\n cssClass: cssClass,\n disableStreamingAnimation: disableStreamingAnimation,\n };\n },\n getAssistantLabel(message) {\n var appearance = message ? this.normalizeAssistantAppearance(message.appearance) : null;\n return appearance && appearance.label ? appearance.label : this.assistantLabel;\n },\n getAssistantRoleClasses(message) {\n var appearance = message ? this.normalizeAssistantAppearance(message.appearance) : null;\n var classes = ['ai-chat-msg-role'];\n\n if (appearance && appearance.cssClass) {\n classes.push(appearance.cssClass);\n } else {\n classes.push('ai-chat-msg-role-assistant');\n }\n\n return classes;\n },\n getAssistantIconClasses(message, index) {\n var appearance = message ? this.normalizeAssistantAppearance(message.appearance) : null;\n return [this.shouldAnimateAssistantIcon(message, index) ? 'ai-streaming-icon' : 'ai-bot-icon', appearance && appearance.cssClass ? appearance.cssClass : ''];\n },\n getAssistantIcon(message) {\n var appearance = message ? this.normalizeAssistantAppearance(message.appearance) : null;\n return appearance && appearance.icon ? appearance.icon : 'fa fa-robot';\n },\n shouldAnimateAssistantIcon(message, index) {\n var appearance = message ? this.normalizeAssistantAppearance(message.appearance) : null;\n return !!message &&\n message.isStreaming &&\n index === this.lastAssistantIndex &&\n !(appearance && appearance.disableStreamingAnimation);\n },\n async startConnection() {\n this.connection = new signalR.HubConnectionBuilder()\n .withUrl(config.signalRHubUrl)\n .withAutomaticReconnect()\n .build();\n\n // Allow long-running operations (e.g., multi-step MCP tool calls)\n // without the client disconnecting prematurely.\n this.connection.serverTimeoutInMilliseconds = 600000;\n this.connection.keepAliveIntervalInMilliseconds = 15000;\n\n this.connection.on(\"LoadSession\", (data) => {\n this.initializeSession(data.sessionId, true);\n this.messages = [];\n this.documents = data.documents || [];\n this.uploadErrors = [];\n\n (data.messages ?? []).forEach(msg => {\n this.addMessage(msg);\n\n this.$nextTick(() => {\n renderChartsInMessage(msg);\n });\n });\n\n // Update feedback icons in the DOM after all messages have rendered.\n this.$nextTick(() => {\n this.refreshAllFeedbackIcons();\n });\n\n // When the session is new (no messages) and an initial prompt is configured,\n // automatically send it as the first user message to trigger an AI response.\n if (this.messages.length === 0 && config.initialPrompt) {\n this.prompt = config.initialPrompt;\n this.sendMessage();\n }\n });\n\n this.connection.on(\"ReceiveError\", (error) => {\n console.error(\"SignalR Error: \", error);\n\n if (this.isRecording) {\n this.stopRecording();\n }\n\n if (widgetBehavior && typeof widgetBehavior.handleReceiveError === 'function') {\n widgetBehavior.handleReceiveError(this, error, config);\n }\n });\n\n this.connection.on(\"MessageRated\", (messageId, userRating) => {\n var msg = this.messages.find(m => m.id === messageId);\n if (msg) {\n msg.userRating = userRating;\n }\n });\n\n this.connection.on(\"ReceiveTranscript\", (sessionId, text, isFinal) => {\n if (this.isConversationMode) {\n if (!isFinal && text) {\n this._conversationPartialTranscript = text;\n var escaped = text.replace(/&/g, '&').replace(//g, '>');\n var html = '

' + escaped + '

';\n\n // Show partial transcript as a live user message.\n if (!this._conversationPartialMessage) {\n this.hidePlaceholder();\n this._conversationPartialMessage = {\n role: 'user',\n content: text,\n htmlContent: html,\n isPartial: true\n };\n this.messages.push(this._conversationPartialMessage);\n } else {\n this._conversationPartialMessage.content = text;\n this._conversationPartialMessage.htmlContent = html;\n }\n this.scrollToBottom();\n }\n return;\n }\n\n if (text && !this._audioInputSent) {\n this.prompt = this.preRecordingPrompt + text;\n if (this.inputElement) {\n this.inputElement.value = this.prompt;\n this.inputElement.dispatchEvent(new Event('input'));\n }\n }\n });\n\n this.connection.on(\"ReceiveConversationUserMessage\", (sessionId, text) => {\n if (text) {\n this.stopAudio();\n\n // If there's an interrupted assistant message still streaming,\n // mark it as done to stop the spinner animation.\n if (this._conversationAssistantMessage) {\n var oldMsg = this.messages[this._conversationAssistantMessage.index];\n if (oldMsg) {\n oldMsg.isStreaming = false;\n }\n this._conversationAssistantMessage = null;\n }\n\n // Replace the partial transcript message with the final one.\n if (this._conversationPartialMessage) {\n var escaped = text.replace(/&/g, '&').replace(//g, '>');\n this._conversationPartialMessage.content = text;\n this._conversationPartialMessage.htmlContent = '

' + escaped + '

';\n this._conversationPartialMessage.isPartial = false;\n this._conversationPartialMessage = null;\n } else {\n this.addMessage({\n role: 'user',\n content: text\n });\n }\n this.scrollToBottom();\n }\n });\n\n this.connection.on(\"ReceiveConversationAssistantToken\", (sessionId, messageId, token, responseId, references, appearance) => {\n if (!this._conversationAssistantMessage) {\n this.stopAudio();\n this.hideTypingIndicator();\n\n // Ensure no stale streaming indicators remain from prior messages.\n for (var j = 0; j < this.messages.length; j++) {\n if (this.messages[j].isStreaming) {\n this.messages[j].isStreaming = false;\n }\n }\n\n var msgIndex = this.messages.length;\n var newMessage = {\n id: messageId,\n role: \"assistant\",\n content: \"\",\n htmlContent: \"\",\n isStreaming: true,\n userRating: null,\n appearance: this.normalizeAssistantAppearance(appearance),\n references: {},\n };\n this.messages.push(newMessage);\n this._conversationAssistantMessage = { index: msgIndex, content: '' };\n }\n\n this._conversationAssistantMessage.content += token;\n var msg = this.messages[this._conversationAssistantMessage.index];\n if (msg) {\n if (!msg.appearance) {\n msg.appearance = this.normalizeAssistantAppearance(appearance);\n }\n msg.rawContent = this._conversationAssistantMessage.content;\n msg.references = normalizeReferences(Object.assign({}, msg.references || {}, references || {}));\n updateMessagePresentation(msg, msg.references);\n this.$nextTick(() => {\n renderChartsInMessage(msg);\n this.scrollToBottom();\n });\n }\n });\n\n this.connection.on(\"ReceiveConversationAssistantComplete\", (sessionId, messageId, references) => {\n if (this._conversationAssistantMessage) {\n var msg = this.messages[this._conversationAssistantMessage.index];\n if (msg) {\n msg.isStreaming = false;\n msg.references = normalizeReferences(Object.assign({}, msg.references || {}, references || {}));\n updateMessagePresentation(msg, msg.references);\n }\n this._conversationAssistantMessage = null;\n }\n });\n\n this.connection.on(\"ReceiveAudioChunk\", (sessionId, base64Audio, contentType) => {\n if (base64Audio) {\n const binaryString = atob(base64Audio);\n const bytes = new Uint8Array(binaryString.length);\n for (let i = 0; i < binaryString.length; i++) {\n bytes[i] = binaryString.charCodeAt(i);\n }\n this.audioChunks.push(bytes);\n }\n });\n\n this.connection.on(\"ReceiveAudioComplete\", (sessionId) => {\n this.playCollectedAudio();\n });\n\n this.connection.on(\"ReceiveNotification\", (notification) => {\n this.receiveNotification(notification);\n });\n\n this.connection.on(\"UpdateNotification\", (notification) => {\n this.updateNotification(notification);\n });\n\n this.connection.on(\"RemoveNotification\", (notificationType) => {\n this.removeNotification(notificationType);\n });\n\n this.connection.onreconnecting(() => {\n console.warn(\"SignalR: reconnecting...\");\n });\n\n this.connection.onreconnected(() => {\n console.info(\"SignalR: reconnected.\");\n\n if (this.isSessionStarted) {\n this.reloadCurrentSession();\n }\n });\n\n this.connection.onclose((error) => {\n if (this.isNavigatingAway) {\n return;\n }\n\n if (error) {\n console.warn(\"SignalR connection closed with error:\", error.message || error);\n }\n });\n\n try {\n await this.connection.start();\n } catch (err) {\n console.error(\"SignalR Connection Error: \", err);\n }\n },\n addMessageInternal(message) {\n if (message.role === 'assistant') {\n message.appearance = this.normalizeAssistantAppearance(message.appearance);\n }\n\n if (message.content && !message.htmlContent) {\n message.htmlContent = parseMarkdownContent(message.content, message);\n }\n this.fireEvent(new CustomEvent(\"addingCoreAIPromotMessage\", { detail: { message: message } }));\n this.messages.push(message);\n\n this.$nextTick(() => {\n this.fireEvent(new CustomEvent(\"addedCoreAIPromotMessage\", { detail: { message: message } }));\n });\n },\n addMessage(message) {\n\n // Ensure userRating is always defined for Vue reactivity.\n if (message.userRating === undefined) {\n message.userRating = null;\n }\n\n if (message.content) {\n message.rawContent = message.rawContent ?? message.content;\n updateMessagePresentation(message, message.references);\n }\n\n this.addMessageInternal(message);\n this.hidePlaceholder();\n\n this.$nextTick(() => {\n // Render any pending charts once the DOM is updated\n renderChartsInMessage(message);\n this.scrollToBottom();\n });\n },\n addMessages(messages) {\n\n for (let i = 0; i < messages.length; i++) {\n this.addMessageInternal(messages[i]);\n }\n\n this.hidePlaceholder();\n this.$nextTick(() => {\n this.scrollToBottom();\n });\n },\n hidePlaceholder() {\n if (this.placeholder) {\n this.placeholder.classList.add('d-none');\n }\n this.isPlaceholderVisible = false;\n },\n showPlaceholder() {\n if (this.placeholder) {\n this.placeholder.classList.remove('d-none');\n }\n this.isPlaceholderVisible = true;\n },\n isOrchestratorAvailable() {\n return config.isOrchestratorAvailable !== false;\n },\n applyOrchestratorAvailability() {\n if (this.isOrchestratorAvailable()) {\n return true;\n }\n\n const unavailableMessage = config.orchestratorUnavailableMessage || \"This orchestrator is not currently available.\";\n\n if (this.inputElement) {\n this.inputElement.disabled = true;\n this.inputElement.value = '';\n this.inputElement.placeholder = unavailableMessage;\n }\n\n if (this.buttonElement) {\n this.buttonElement.disabled = true;\n }\n\n if (this.micButtonElement) {\n this.micButtonElement.disabled = true;\n this.micButtonElement.style.display = 'none';\n }\n\n if (this.conversationButtonElement) {\n this.conversationButtonElement.disabled = true;\n this.conversationButtonElement.style.display = 'none';\n }\n\n return false;\n },\n fireEvent(event) {\n document.dispatchEvent(event);\n },\n isIndicator(message) {\n return message.role === 'indicator';\n },\n sendMessage() {\n if (!this.applyOrchestratorAvailability()) {\n return;\n }\n\n let trimmedPrompt = this.prompt.trim();\n\n if (!trimmedPrompt) {\n return;\n }\n\n // Stop any active recording before sending.\n if (this.isRecording) {\n this.stopRecording();\n }\n\n // Prevent stale ReceiveTranscript events from repopulating the prompt.\n this._audioInputSent = true;\n\n // In single-response mode, clear all previous messages.\n if (this.singleResponseMode) {\n this.messages.splice(0, this.messages.length);\n }\n\n this.addMessage({\n role: 'user',\n content: trimmedPrompt\n });\n\n this.streamMessage(this.getProfileId(), trimmedPrompt, null);\n this.inputElement.value = '';\n this.prompt = '';\n },\n startRecording() {\n if (this.isRecording || !this.connection) {\n return;\n }\n\n navigator.mediaDevices.getUserMedia({ audio: { echoCancellation: true, noiseSuppression: true, autoGainControl: true } })\n .then(stream => {\n var mimeType = MediaRecorder.isTypeSupported('audio/ogg;codecs=opus')\n ? 'audio/ogg;codecs=opus'\n : MediaRecorder.isTypeSupported('audio/webm;codecs=opus')\n ? 'audio/webm;codecs=opus'\n : 'audio/webm';\n\n this.mediaRecorder = new MediaRecorder(stream, {\n mimeType: mimeType,\n audioBitsPerSecond: 128000,\n });\n\n this.preRecordingPrompt = this.prompt;\n this._audioInputSent = false;\n\n var subject = new signalR.Subject();\n var profileId = this.getProfileId();\n var sessionId = this.getSessionId() || '';\n var pendingChunk = Promise.resolve();\n\n this.mediaRecorder.addEventListener('dataavailable', (e) => {\n if (e.data && e.data.size > 0) {\n pendingChunk = pendingChunk.then(async () => {\n var data = await e.data.arrayBuffer();\n var uint8Array = new Uint8Array(data);\n var binaryString = uint8Array.reduce(function (str, byte) { return str + String.fromCharCode(byte); }, '');\n var base64 = btoa(binaryString);\n subject.next(base64);\n });\n }\n });\n\n this.mediaRecorder.addEventListener('stop', () => {\n stream.getTracks().forEach(track => track.stop());\n pendingChunk.then(() => subject.complete());\n });\n\n var language = navigator.language || document.documentElement.lang || 'en-US';\n this.connection.send(\"SendAudioStream\", profileId, sessionId, subject, mimeType, language);\n this.mediaRecorder.start(250);\n this.isRecording = true;\n this.updateMicButton();\n })\n .catch(err => {\n console.error('Microphone access denied:', err);\n });\n },\n stopRecording() {\n if (!this.isRecording || !this.mediaRecorder) {\n return;\n }\n\n this.mediaRecorder.stop();\n this.isRecording = false;\n this.updateMicButton();\n },\n toggleRecording() {\n if (this.isRecording) {\n this.stopRecording();\n } else {\n this.startRecording();\n }\n },\n updateMicButton() {\n if (!this.micButton) {\n return;\n }\n\n if (this.isRecording) {\n this.micButton.classList.add('stt-recording');\n this.micButton.innerHTML = '';\n } else {\n this.micButton.classList.remove('stt-recording');\n this.micButton.innerHTML = '';\n }\n },\n streamMessage(profileId, trimmedPrompt, sessionProfileId) {\n\n if (this.stream) {\n this.stream.dispose();\n this.stream = null;\n }\n\n this.streamingStarted();\n this.showTypingIndicator();\n this.autoScroll = true;\n\n var content = '';\n var references = {};\n var lastResponseId = null;\n\n // Get the index after showing typing indicator.\n var messageIndex = this.messages.length;\n var currentSessionId = this.getSessionId();\n\n this.stream = this.connection.stream(\"SendMessage\", profileId, trimmedPrompt, currentSessionId, sessionProfileId)\n .subscribe({\n next: (chunk) => {\n let message = this.messages[messageIndex];\n\n if (!message) {\n\n if (chunk.sessionId && !currentSessionId) {\n this.initializeSession(chunk.sessionId);\n }\n\n this.hideTypingIndicator();\n // Re-assign the index after hiding the typing indicator.\n messageIndex = this.messages.length;\n let newMessage = {\n id: chunk.messageId,\n role: \"assistant\",\n title: chunk.title,\n content: \"\",\n htmlContent: \"\",\n isStreaming: true,\n userRating: null,\n };\n\n this.messages.push(newMessage);\n\n message = newMessage;\n }\n\n if (chunk.title && (!message.title || message.title !== chunk.title)) {\n message.title = chunk.title;\n }\n\n if (chunk.references && typeof chunk.references === \"object\" && Object.keys(chunk.references).length) {\n\n for (const [key, value] of Object.entries(chunk.references)) {\n references[key] = normalizeReference(value) ?? {};\n }\n }\n\n if (chunk.content) {\n\n // When the responseId changes (e.g., after an internal tool call),\n // insert a line break to visually separate response segments.\n if (chunk.responseId && lastResponseId && chunk.responseId !== lastResponseId) {\n content += '\\n\\n';\n }\n\n if (chunk.responseId) {\n lastResponseId = chunk.responseId;\n }\n\n content += chunk.content;\n }\n\n // Update the existing message\n message.rawContent = content;\n updateMessagePresentation(message, references);\n\n this.messages[messageIndex] = message;\n\n this.$nextTick(() => {\n renderChartsInMessage(message);\n this.scrollToBottom();\n });\n },\n complete: () => {\n this.processReferences(references, messageIndex);\n this.streamingFinished();\n\n let msg = this.messages[messageIndex];\n if (msg) {\n msg.isStreaming = false;\n }\n\n if (!msg || !msg.content) {\n // No content received at all.\n this.hideTypingIndicator();\n }\n\n // Trigger text-to-speech only in conversation mode.\n if (this.isConversationMode && this.textToSpeechEnabled && msg && msg.content) {\n this.synthesizeSpeech(msg.content);\n }\n\n this.stream?.dispose();\n this.stream = null;\n },\n error: (err) => {\n this.processReferences(references, messageIndex);\n this.streamingFinished();\n\n let msg = this.messages[messageIndex];\n if (msg) {\n msg.isStreaming = false;\n }\n\n this.hideTypingIndicator();\n\n if (!this.isNavigatingAway) {\n this.addMessage(this.getServiceDownMessage());\n }\n\n this.stream?.dispose();\n this.stream = null;\n\n console.error(\"Stream error:\", err);\n }\n });\n },\n getServiceDownMessage() {\n let newMessage = {\n role: \"assistant\",\n content: \"Our service is currently unavailable. Please try again later. We apologize for the inconvenience.\",\n htmlContent: \"\",\n };\n\n return newMessage;\n },\n processReferences(references, messageIndex) {\n references = normalizeReferences(references);\n\n if (Object.keys(references).length) {\n\n let message = this.messages[messageIndex];\n message.rawContent = message.rawContent ?? message.content ?? '';\n updateMessagePresentation(message, references);\n\n this.messages[messageIndex] = message;\n\n this.$nextTick(() => {\n renderChartsInMessage(message);\n this.scrollToBottom();\n });\n }\n },\n streamingStarted() {\n var stopIcon = this.buttonElement.getAttribute('data-stop-icon');\n\n if (stopIcon) {\n this.buttonElement.replaceChildren(DOMPurify.sanitize(stopIcon, { RETURN_DOM_FRAGMENT: true }));\n }\n\n if (this.inputElement) {\n this.inputElement.setAttribute('disabled', 'disabled');\n }\n },\n streamingFinished() {\n var startIcon = this.buttonElement.getAttribute('data-start-icon');\n\n if (startIcon) {\n this.buttonElement.replaceChildren(DOMPurify.sanitize(startIcon, { RETURN_DOM_FRAGMENT: true }));\n }\n\n if (this.inputElement) {\n this.inputElement.removeAttribute('disabled');\n this.inputElement.focus();\n }\n\n // Directly manipulate the DOM to stop all streaming animations.\n if (this.chatContainer) {\n var icons = this.chatContainer.querySelectorAll('.ai-streaming-icon');\n for (var i = 0; i < icons.length; i++) {\n icons[i].classList.remove('ai-streaming-icon');\n icons[i].classList.add('ai-bot-icon');\n }\n }\n\n // Also update Vue data for consistency.\n for (var i = 0; i < this.messages.length; i++) {\n if (this.messages[i].isStreaming) {\n this.messages[i].isStreaming = false;\n }\n }\n },\n handleExternalTtsStop(e) {\n if (e?.detail?.sourceId === this.ttsInstanceId) {\n return;\n }\n\n this.stopAudio(false);\n },\n updateTtsPlaybackButtons() {\n if (!this.chatContainer) {\n return;\n }\n\n var buttons = this.chatContainer.querySelectorAll('[data-tts-message-index]');\n\n buttons.forEach(button => {\n var buttonIndex = Number(button.getAttribute('data-tts-message-index'));\n var isPlaying = buttonIndex === this.ttsPlayingMessageIndex;\n\n button.classList.toggle('tts-playing', isPlaying);\n button.setAttribute('title', isPlaying ? 'Pause audio' : 'Read aloud');\n });\n },\n updateCopyButtons() {\n if (!this.chatContainer) {\n return;\n }\n\n var buttons = this.chatContainer.querySelectorAll('[data-copy-message-index]');\n\n buttons.forEach(button => {\n var buttonIndex = Number(button.getAttribute('data-copy-message-index'));\n var isCopied = buttonIndex === this.copiedMessageIndex;\n var iconHtml = isCopied\n ? ''\n : '';\n\n button.classList.toggle('text-success', isCopied);\n button.classList.toggle('text-secondary', !isCopied);\n button.setAttribute('title', isCopied ? this.copiedTitle : this.copyTitle);\n button.replaceChildren(DOMPurify.sanitize(iconHtml, { RETURN_DOM_FRAGMENT: true }));\n });\n },\n setCopyButtonState(button, isCopied) {\n if (!button) {\n return;\n }\n\n var iconHtml = isCopied\n ? ''\n : '';\n\n button.classList.toggle('text-success', isCopied);\n button.classList.toggle('text-secondary', !isCopied);\n button.setAttribute('title', isCopied ? this.copiedTitle : this.copyTitle);\n button.replaceChildren(DOMPurify.sanitize(iconHtml, { RETURN_DOM_FRAGMENT: true }));\n },\n synthesizeSpeech(text, cacheIndex) {\n if (!this.textToSpeechEnabled || !text || !this.connection) {\n return;\n }\n\n this.audioChunks = [];\n this.isPlayingAudio = true;\n this._ttsCacheIndex = cacheIndex !== undefined ? cacheIndex : -1;\n\n this.connection.invoke(\"SynthesizeSpeech\", this.getProfileId(), this.getSessionId(), text, this.ttsVoiceName)\n .catch(err => {\n console.error(\"TTS synthesis error:\", err);\n this.isPlayingAudio = false;\n this.ttsPlayingMessageIndex = -1;\n this._ttsCacheIndex = -1;\n this.$nextTick(() => this.updateTtsPlaybackButtons());\n });\n },\n toggleMessageTts(message, index) {\n if (this.ttsPlayingMessageIndex === index) {\n this.stopAudio();\n return;\n }\n\n this.stopAudio(false);\n window.dispatchEvent(new CustomEvent('crestapps-ai-chat-stop-tts', {\n detail: { sourceId: this.ttsInstanceId }\n }));\n this.ttsPlayingMessageIndex = index;\n this.$nextTick(() => this.updateTtsPlaybackButtons());\n\n if (this.ttsAudioCache[index]) {\n this.playAudioBlob(this.ttsAudioCache[index]);\n return;\n }\n\n this.synthesizeSpeech(message.content, index);\n },\n playCollectedAudio() {\n if (this.audioChunks.length === 0) {\n if (!this.currentAudioElement && this.audioPlayQueue.length === 0) {\n this.isPlayingAudio = false;\n this.ttsPlayingMessageIndex = -1;\n this.$nextTick(() => this.updateTtsPlaybackButtons());\n }\n return;\n }\n\n const totalLength = this.audioChunks.reduce((sum, chunk) => sum + chunk.length, 0);\n const combined = new Uint8Array(totalLength);\n let offset = 0;\n for (const chunk of this.audioChunks) {\n combined.set(chunk, offset);\n offset += chunk.length;\n }\n this.audioChunks = [];\n\n const blob = new Blob([combined], { type: 'audio/mp3' });\n\n if (this._ttsCacheIndex >= 0) {\n this.ttsAudioCache[this._ttsCacheIndex] = blob;\n this._ttsCacheIndex = -1;\n }\n\n // If audio is already playing, queue this blob for sequential playback.\n if (this.currentAudioElement) {\n this.audioPlayQueue.push(blob);\n return;\n }\n\n this.playAudioBlob(blob);\n },\n playAudioBlob(blob) {\n const url = URL.createObjectURL(blob);\n const audio = new Audio(url);\n\n this.currentAudioUrl = url;\n this.currentAudioElement = audio;\n this.isPlayingAudio = true;\n\n audio.addEventListener('ended', () => {\n this.currentAudioElement = null;\n this.currentAudioUrl = null;\n URL.revokeObjectURL(url);\n this.playNextInQueue();\n });\n\n audio.addEventListener('error', () => {\n this.currentAudioElement = null;\n this.currentAudioUrl = null;\n URL.revokeObjectURL(url);\n this.playNextInQueue();\n });\n\n audio.play().catch(err => {\n console.error(\"Audio playback error:\", err);\n this.currentAudioElement = null;\n this.currentAudioUrl = null;\n URL.revokeObjectURL(url);\n this.audioPlayQueue = [];\n this.isPlayingAudio = false;\n this.ttsPlayingMessageIndex = -1;\n this.$nextTick(() => this.updateTtsPlaybackButtons());\n });\n },\n playNextInQueue() {\n if (this.audioPlayQueue.length > 0) {\n var nextBlob = this.audioPlayQueue.shift();\n this.playAudioBlob(nextBlob);\n } else {\n this.isPlayingAudio = false;\n this.ttsPlayingMessageIndex = -1;\n this.$nextTick(() => this.updateTtsPlaybackButtons());\n this.conversationModeOnAudioEnded();\n }\n },\n stopAudio() {\n if (this.currentAudioElement) {\n this.currentAudioElement.pause();\n this.currentAudioElement.currentTime = 0;\n this.currentAudioElement = null;\n }\n if (this.currentAudioUrl) {\n URL.revokeObjectURL(this.currentAudioUrl);\n this.currentAudioUrl = null;\n }\n this.audioChunks = [];\n this.audioPlayQueue = [];\n this.isPlayingAudio = false;\n this.ttsPlayingMessageIndex = -1;\n this.$nextTick(() => this.updateTtsPlaybackButtons());\n },\n toggleConversationMode() {\n if (this.isConversationMode) {\n this.stopConversationMode();\n } else {\n this.startConversationMode();\n }\n },\n startConversationMode() {\n if (!this.conversationModeEnabled || this.isConversationMode || !this.connection) {\n return;\n }\n\n this.isConversationMode = true;\n this.updateConversationButton();\n this._conversationPartialTranscript = '';\n this._conversationAssistantMessage = null;\n this._conversationPartialMessage = null;\n\n // Remove any previous conversation ended notification.\n this.removeNotification('conversation-ended');\n navigator.mediaDevices.getUserMedia({ audio: { echoCancellation: true, noiseSuppression: true, autoGainControl: true } })\n .then(stream => {\n var mimeType = MediaRecorder.isTypeSupported('audio/ogg;codecs=opus')\n ? 'audio/ogg;codecs=opus'\n : MediaRecorder.isTypeSupported('audio/webm;codecs=opus')\n ? 'audio/webm;codecs=opus'\n : 'audio/webm';\n\n this.mediaRecorder = new MediaRecorder(stream, {\n mimeType: mimeType,\n audioBitsPerSecond: 128000,\n });\n\n this._conversationSubject = new signalR.Subject();\n this._conversationStream = stream;\n\n // Create an AnalyserNode for volume-based interrupt detection.\n // During TTS playback, detect when the user speaks above\n // the threshold to stop TTS (interrupt). Audio chunks are\n // always forwarded — browser echo cancellation handles\n // speaker echo so the STT stream has no gaps.\n var AudioCtx = window.AudioContext || window.webkitAudioContext;\n if (AudioCtx) {\n this._conversationAudioCtx = new AudioCtx();\n this._conversationAnalyser = this._conversationAudioCtx.createAnalyser();\n this._conversationAnalyser.fftSize = 256;\n var micSource = this._conversationAudioCtx.createMediaStreamSource(stream);\n micSource.connect(this._conversationAnalyser);\n }\n\n var pendingChunk = Promise.resolve();\n var analyser = this._conversationAnalyser;\n var interruptVolumeThreshold = 30;\n\n this.mediaRecorder.addEventListener('dataavailable', (e) => {\n if (e.data && e.data.size > 0) {\n // During TTS playback, check mic volume to detect\n // user interruption (speaking above threshold).\n if (this.isPlayingAudio && analyser) {\n var freqData = new Uint8Array(analyser.frequencyBinCount);\n analyser.getByteFrequencyData(freqData);\n var sum = 0;\n for (var k = 0; k < freqData.length; k++) { sum += freqData[k]; }\n var avg = sum / freqData.length;\n\n if (avg >= interruptVolumeThreshold) {\n // User is speaking — interrupt TTS playback.\n this.stopAudio();\n }\n }\n\n // Always send audio to STT — browser echo cancellation\n // handles speaker echo; continuous audio avoids gaps\n // that increase recognition latency.\n pendingChunk = pendingChunk.then(async () => {\n var data = await e.data.arrayBuffer();\n var uint8Array = new Uint8Array(data);\n var binaryString = uint8Array.reduce(function (str, byte) { return str + String.fromCharCode(byte); }, '');\n var base64 = btoa(binaryString);\n try {\n this._conversationSubject.next(base64);\n } catch (err) {\n // Subject may have been completed already.\n }\n });\n }\n });\n\n this.mediaRecorder.addEventListener('stop', () => {\n stream.getTracks().forEach(track => track.stop());\n pendingChunk.then(() => {\n try {\n this._conversationSubject.complete();\n } catch (err) {\n // Already completed.\n }\n });\n });\n\n var profileId = this.getProfileId();\n var sessionId = this.getSessionId() || '';\n var language = navigator.language || document.documentElement.lang || 'en-US';\n\n this.connection.send(\"StartConversation\", profileId, sessionId, this._conversationSubject, mimeType, language);\n this.mediaRecorder.start(250);\n this.isRecording = true;\n })\n .catch(err => {\n console.error('Microphone access denied:', err);\n this.isConversationMode = false;\n this.updateConversationButton();\n });\n },\n stopConversationMode() {\n if (!this.isConversationMode) {\n return;\n }\n\n this.isConversationMode = false;\n this.updateConversationButton();\n\n // Signal the server to cancel all in-progress STT/TTS streams immediately.\n if (this.connection) {\n this.connection.invoke(\"StopConversation\").catch(function () { });\n }\n\n if (this.isRecording && this.mediaRecorder) {\n this.mediaRecorder.stop();\n this.isRecording = false;\n }\n\n this.stopAudio();\n this._conversationPartialTranscript = '';\n this._conversationPartialMessage = null;\n\n // Clean up the AudioContext used for volume monitoring.\n if (this._conversationAudioCtx) {\n this._conversationAudioCtx.close().catch(function () { });\n this._conversationAudioCtx = null;\n this._conversationAnalyser = null;\n }\n\n // Mark any in-flight assistant message as done to stop the spinner.\n if (this._conversationAssistantMessage) {\n var msg = this.messages[this._conversationAssistantMessage.index];\n if (msg) {\n msg.isStreaming = false;\n }\n this._conversationAssistantMessage = null;\n }\n\n // Safety net: clear all lingering streaming indicators.\n for (var i = 0; i < this.messages.length; i++) {\n if (this.messages[i].isStreaming) {\n this.messages[i].isStreaming = false;\n }\n }\n\n // Show a \"conversation ended\" notification system message.\n this.receiveNotification({\n type: 'conversation-ended',\n content: 'Conversation ended.',\n icon: 'fa-solid fa-circle-check',\n dismissible: true,\n autoDismissMs: 5000\n });\n },\n updateConversationButton() {\n if (!this.conversationButton) {\n return;\n }\n\n if (this.isConversationMode) {\n this.conversationButton.classList.add('active', 'btn-primary');\n this.conversationButton.classList.remove('btn-dark', 'btn-outline-dark', 'btn-outline-secondary');\n this.conversationButton.title = this.conversationButton.getAttribute('data-end-title') || 'End Conversation';\n var endHtml = this.conversationButton.getAttribute('data-end-html');\n if (endHtml) {\n this.conversationButton.replaceChildren(DOMPurify.sanitize(endHtml, { RETURN_DOM_FRAGMENT: true }));\n }\n } else {\n this.conversationButton.classList.remove('active', 'btn-primary');\n this.conversationButton.classList.remove('btn-dark', 'btn-outline-secondary');\n this.conversationButton.classList.add('btn-outline-dark');\n this.conversationButton.blur();\n this.conversationButton.title = this.conversationButton.getAttribute('data-start-title') || 'Start Conversation';\n var startHtml = this.conversationButton.getAttribute('data-start-html');\n if (startHtml) {\n this.conversationButton.replaceChildren(DOMPurify.sanitize(startHtml, { RETURN_DOM_FRAGMENT: true }));\n }\n }\n },\n conversationModeSendPrompt() {\n // Legacy: only used by AudioInput mode's ReceiveTranscript.\n },\n conversationModeOnAudioEnded() {\n // Legacy: in conversation mode, audio playback continuation\n // is handled by the persistent stream. This method is only\n // called from playCollectedAudio for non-conversation TTS.\n },\n generatePrompt(element) {\n if (!element) {\n console.error('The element paramter is required.');\n\n return;\n }\n\n let templateProfileId = element.getAttribute('data-profile-id');\n let sessionId = this.getSessionId();\n let sessionProfileId = this.getProfileId();\n\n if (!templateProfileId || !sessionId) {\n\n console.error('The given element is missing data-profile-id or the session has not yet started.');\n return;\n }\n\n // streamMessage() already shows the typing indicator.\n this.streamMessage(templateProfileId, null, sessionProfileId);\n },\n createSessionUrl(baseUrl, param, value) {\n\n const fullUrl = baseUrl.toLowerCase().startsWith('http') ? baseUrl : window.location.origin + baseUrl;\n const url = new URL(fullUrl);\n\n url.searchParams.set(param, value);\n\n return url.toString();\n },\n showTypingIndicator() {\n this.addMessage({\n role: 'indicator',\n htmlContent: config.indicatorTemplate\n });\n },\n hideTypingIndicator() {\n const originalLength = this.messages.length;\n this.messages = this.messages.filter(msg => msg.role !== 'indicator');\n const removedCount = originalLength - this.messages.length;\n return removedCount;\n },\n receiveNotification(notification) {\n if (!notification || !notification.type) {\n return;\n }\n this.clearNotificationDismiss(notification.type);\n var existingIndex = this.notifications.findIndex(n => n.type === notification.type);\n if (existingIndex >= 0) {\n this.notifications.splice(existingIndex, 1, notification);\n } else {\n this.notifications.push(notification);\n }\n this.scheduleNotificationDismiss(notification);\n this.$nextTick(() => {\n this.scrollToBottom();\n });\n },\n updateNotification(notification) {\n if (!notification || !notification.type) {\n return;\n }\n this.clearNotificationDismiss(notification.type);\n var existingIndex = this.notifications.findIndex(n => n.type === notification.type);\n if (existingIndex >= 0) {\n this.notifications.splice(existingIndex, 1, notification);\n this.scheduleNotificationDismiss(notification);\n }\n },\n scheduleNotificationDismiss(notification) {\n if (!notification || !notification.type || !notification.autoDismissMs || notification.autoDismissMs <= 0) {\n return;\n }\n this.notificationDismissTimers[notification.type] = setTimeout(() => {\n this.removeNotification(notification.type);\n }, notification.autoDismissMs);\n },\n clearNotificationDismiss(notificationType) {\n var timerId = this.notificationDismissTimers[notificationType];\n if (!timerId) {\n return;\n }\n clearTimeout(timerId);\n delete this.notificationDismissTimers[notificationType];\n },\n removeNotification(notificationType) {\n this.clearNotificationDismiss(notificationType);\n this.notifications = this.notifications.filter(n => n.type !== notificationType);\n },\n dismissNotification(notificationType) {\n this.removeNotification(notificationType);\n },\n handleNotificationAction(notificationType, actionName) {\n if (!this.connection) {\n return;\n }\n var sessionId = this.getSessionId();\n this.connection.invoke(\"HandleNotificationAction\", sessionId, notificationType, actionName).catch(function (err) {\n console.error(\"Error handling notification action:\", err);\n });\n },\n scrollToBottom() {\n if (!this.autoScroll) {\n return;\n }\n setTimeout(() => {\n this.chatContainer.scrollTop = this.chatContainer.scrollHeight - this.chatContainer.clientHeight;\n }, 50);\n },\n handleUserInput(event) {\n this.prompt = event.target.value;\n },\n getProfileId() {\n return this.inputElement\n ? this.inputElement.getAttribute('data-profile-id')\n : null;\n },\n setSessionId(sessionId) {\n if (!this.inputElement) {\n return;\n }\n\n this.inputElement.setAttribute('data-session-id', sessionId || '');\n },\n resetSession() {\n this.stopRecording();\n this.rejectPendingSessionRequest('Session was reset.');\n this.setSessionId('');\n this.isSessionStarted = false;\n this.sessionRating = null;\n this.messages = [];\n this.documents = [];\n this.showPlaceholder();\n\n if (widgetBehavior && typeof widgetBehavior.onSessionReset === 'function') {\n widgetBehavior.onSessionReset(this, config);\n }\n },\n startNewSession() {\n if (!this.applyOrchestratorAvailability()) {\n return;\n }\n\n const profileId = this.getProfileId();\n if (!profileId || !this.connection) {\n return;\n }\n\n this.requestNewSession(profileId).catch(err => console.error(err));\n },\n async ensureSessionForDocuments(profileId) {\n var sessionId = this.getSessionId();\n if (sessionId) {\n return sessionId;\n }\n\n if (!profileId || !this.connection) {\n return null;\n }\n\n return await this.requestNewSession(profileId);\n },\n requestNewSession(profileId) {\n if (this.pendingSessionPromise) {\n return this.pendingSessionPromise;\n }\n\n if (!profileId || !this.connection) {\n return Promise.resolve(null);\n }\n\n this.pendingSessionPromise = new Promise((resolve, reject) => {\n this.pendingSessionResolver = resolve;\n this.pendingSessionRejector = reject;\n this.pendingSessionTimeoutId = window.setTimeout(() => {\n this.rejectPendingSessionRequest('Timed out while creating a chat session.');\n }, 15000);\n });\n\n this.connection.invoke(\"StartSession\", profileId, null).catch(err => {\n this.rejectPendingSessionRequest(err);\n });\n\n return this.pendingSessionPromise;\n },\n resolvePendingSessionRequest(sessionId) {\n if (this.pendingSessionResolver) {\n this.pendingSessionResolver(sessionId);\n }\n\n this.clearPendingSessionRequest();\n },\n rejectPendingSessionRequest(error) {\n if (this.pendingSessionRejector) {\n this.pendingSessionRejector(error);\n }\n\n this.clearPendingSessionRequest();\n },\n clearPendingSessionRequest() {\n if (this.pendingSessionTimeoutId) {\n window.clearTimeout(this.pendingSessionTimeoutId);\n }\n\n this.pendingSessionPromise = null;\n this.pendingSessionResolver = null;\n this.pendingSessionRejector = null;\n this.pendingSessionTimeoutId = null;\n },\n initializeApp() {\n this.inputElement = document.querySelector(config.inputElementSelector);\n this.buttonElement = document.querySelector(config.sendButtonElementSelector);\n this.chatContainer = document.querySelector(config.chatContainerElementSelector);\n this.placeholder = document.querySelector(config.placeholderElementSelector);\n\n if (!this.inputElement || !this.buttonElement || !this.chatContainer || !this.placeholder) {\n console.error('AI chat app could not initialize because one or more required elements were not found.', {\n inputElementSelector: config.inputElementSelector,\n sendButtonElementSelector: config.sendButtonElementSelector,\n chatContainerElementSelector: config.chatContainerElementSelector,\n placeholderElementSelector: config.placeholderElementSelector\n });\n\n return false;\n }\n\n this.applyOrchestratorAvailability();\n\n const sessionId = this.getSessionId();\n if (!hasWidgetConfig && sessionId) {\n this.loadSession(sessionId);\n }\n\n // Initialize document bar if enabled.\n if (config.sessionDocumentsEnabled && config.documentBarSelector) {\n this.documentBar = document.querySelector(config.documentBarSelector);\n if (this.documentBar) {\n this.renderDocumentBar();\n\n // Create hidden file input for document uploads.\n var fileInput = document.createElement('input');\n fileInput.type = 'file';\n fileInput.id = 'ai-chat-doc-input';\n fileInput.className = 'd-none';\n fileInput.multiple = true;\n if (config.allowedExtensions) {\n fileInput.accept = config.allowedExtensions;\n }\n fileInput.addEventListener('change', (e) => this.handleFileInputChange(e));\n this.documentBar.parentElement.appendChild(fileInput);\n\n // Set up drag-and-drop on the input area.\n var inputArea = this.inputElement ? this.inputElement.closest('.ai-admin-widget-input, .text-bg-light') : null;\n if (inputArea) {\n inputArea.addEventListener('dragover', (e) => this.handleDragOver(e));\n inputArea.addEventListener('dragleave', (e) => this.handleDragLeave(e));\n inputArea.addEventListener('drop', (e) => this.handleDrop(e));\n }\n }\n }\n\n // Pause auto-scroll when the user manually scrolls up during streaming.\n this.chatContainer.addEventListener('scroll', () => {\n if (!this.stream) {\n return;\n }\n const threshold = 30;\n const atBottom = this.chatContainer.scrollHeight - this.chatContainer.clientHeight - this.chatContainer.scrollTop <= threshold;\n this.autoScroll = atBottom;\n });\n\n this.inputElement.addEventListener('keydown', event => {\n\n if (this.stream != null) {\n return;\n }\n\n if (event.key === \"Enter\" && !event.shiftKey) {\n event.preventDefault();\n this.buttonElement.click();\n }\n });\n\n this.inputElement.addEventListener('input', (e) => {\n this.handleUserInput(e);\n\n if (e.target.value.trim()) {\n this.buttonElement.removeAttribute('disabled');\n } else {\n this.buttonElement.setAttribute('disabled', true);\n }\n });\n\n this.buttonElement.addEventListener('click', () => {\n\n if (this.stream != null) {\n this.stream.dispose();\n this.stream = null;\n\n this.streamingFinished();\n this.hideTypingIndicator();\n\n // Clean up: remove empty assistant message or stop streaming animation.\n if (this.messages.length > 0) {\n const lastMsg = this.messages[this.messages.length - 1];\n if (lastMsg.role === 'assistant' && !lastMsg.content) {\n this.messages.pop();\n } else if (lastMsg.isStreaming) {\n lastMsg.isStreaming = false;\n }\n }\n\n return;\n }\n\n this.sendMessage();\n });\n\n const promptGenerators = document.getElementsByClassName('profile-generated-prompt');\n\n for (var i = 0; i < promptGenerators.length; i++) {\n promptGenerators[i].addEventListener('click', (e) => {\n e.preventDefault();\n this.generatePrompt(e.target);\n });\n }\n\n const chatSessions = document.getElementsByClassName('chat-session-history-item');\n\n for (var i = 0; i < chatSessions.length; i++) {\n chatSessions[i].addEventListener('click', (e) => {\n e.preventDefault();\n\n var sessionId = e.target.getAttribute('data-session-id');\n\n if (!sessionId) {\n console.error('an element with the class chat-session-history-item with no data-session-id set.');\n\n return;\n }\n\n this.loadSession(sessionId);\n this.showChatScreen();\n });\n }\n\n const initialMessages = Array.isArray(config.messages) ? config.messages : [];\n\n for (let i = 0; i < initialMessages.length; i++) {\n this.addMessage(initialMessages[i]);\n }\n\n // Update feedback icons in the DOM after initial messages have rendered.\n this.$nextTick(() => {\n this.refreshAllFeedbackIcons();\n });\n\n // Delegate click for code block copy buttons.\n if (this.chatContainer) {\n this.chatContainer.addEventListener('click', (e) => {\n var btn = e.target.closest('.ai-code-copy-btn');\n if (!btn) {\n return;\n }\n\n var block = btn.closest('.ai-code-block') || btn.closest('pre');\n if (!block) {\n return;\n }\n\n var codeEl = block.querySelector('code');\n if (codeEl) {\n navigator.clipboard.writeText(codeEl.textContent);\n var copiedText = config.codeCopiedText || 'Copied!';\n btn.innerHTML = ' ' + copiedText;\n setTimeout(() => {\n btn.innerHTML = '';\n }, 2000);\n }\n });\n }\n\n // Initialize speech-to-text microphone button.\n if (this.speechToTextEnabled && config.micButtonElementSelector) {\n this.micButton = document.querySelector(config.micButtonElementSelector);\n if (this.micButton) {\n this.micButton.style.display = '';\n this.micButton.addEventListener('click', () => {\n this.toggleRecording();\n });\n }\n }\n\n // Initialize conversation mode button.\n if (this.conversationModeEnabled && config.conversationButtonElementSelector) {\n this.conversationButton = document.querySelector(config.conversationButtonElementSelector);\n if (this.conversationButton) {\n this.conversationButton.addEventListener('click', () => {\n this.toggleConversationMode();\n });\n }\n }\n\n return true;\n },\n loadSession(sessionId) {\n this.connection.invoke(\"LoadSession\", sessionId).catch(err => console.error(err));\n },\n reloadCurrentSession() {\n\n var sessionId = this.getSessionId();\n if (sessionId) {\n this.loadSession(sessionId);\n }\n },\n initializeSession(sessionId, force) {\n if (this.isSessionStarted && !force) {\n if (sessionId && this.getSessionId() === sessionId) {\n this.resolvePendingSessionRequest(sessionId);\n }\n\n return\n }\n this.fireEvent(new CustomEvent(\"initializingSessionCoreAIChat\", { detail: { sessionId: sessionId } }))\n this.setSessionId(sessionId);\n this.isSessionStarted = true;\n this.resolvePendingSessionRequest(sessionId);\n\n if (widgetBehavior && typeof widgetBehavior.onSessionInitialized === 'function') {\n widgetBehavior.onSessionInitialized(this, sessionId, config);\n }\n },\n getSessionId() {\n let sessionId = this.inputElement\n ? this.inputElement.getAttribute('data-session-id')\n : null;\n\n if (!sessionId && widgetBehavior && typeof widgetBehavior.resolveSessionId === 'function') {\n sessionId = widgetBehavior.resolveSessionId(this, config);\n }\n\n return sessionId;\n },\n clearCopiedMessageState() {\n if (this.copyResetTimeoutId) {\n window.clearTimeout(this.copyResetTimeoutId);\n this.copyResetTimeoutId = null;\n }\n\n if (this.activeCopyButton) {\n this.setCopyButtonState(this.activeCopyButton, false);\n this.activeCopyButton = null;\n }\n\n this.copiedMessageIndex = -1;\n },\n copyResponse(message, index, event) {\n const text = message && typeof message === 'object'\n ? message.copyContent ?? message.content ?? ''\n : message ?? '';\n const button = event?.currentTarget || event?.target?.closest?.('[data-copy-message-index]') || null;\n\n navigator.clipboard.writeText(text)\n .then(() => {\n this.clearCopiedMessageState();\n this.copiedMessageIndex = typeof index === 'number' ? index : -1;\n this.activeCopyButton = button;\n\n if (button) {\n this.setCopyButtonState(button, true);\n } else {\n this.$nextTick(() => this.updateCopyButtons());\n }\n\n this.copyResetTimeoutId = window.setTimeout(() => {\n this.clearCopiedMessageState();\n this.$nextTick(() => this.updateCopyButtons());\n }, Number(config.copyResetDelayMs) || 2000);\n })\n .catch(err => console.error('Failed to copy response:', err));\n },\n updateFeedbackIcons(container, userRating) {\n if (!container) {\n return;\n }\n\n var upBtn = container.querySelector('.rate-up-btn');\n var downBtn = container.querySelector('.rate-down-btn');\n\n // Keep feedback icons as simple span-based Font Awesome markup so\n // later state updates do not depend on i2svg replacement.\n if (upBtn) {\n var upClass = userRating === true ? 'fa-solid fa-thumbs-up' : 'fa-regular fa-thumbs-up';\n var upIcon = document.createElement('span');\n upIcon.className = upClass;\n upIcon.style.fontSize = '0.9rem';\n upBtn.textContent = '';\n upBtn.appendChild(upIcon);\n }\n\n if (downBtn) {\n var downClass = userRating === false ? 'fa-solid fa-thumbs-down' : 'fa-regular fa-thumbs-down';\n var downIcon = document.createElement('span');\n downIcon.className = downClass;\n downIcon.style.fontSize = '0.9rem';\n downBtn.textContent = '';\n downBtn.appendChild(downIcon);\n }\n },\n refreshAllFeedbackIcons() {\n var containers = this.$el.querySelectorAll('.ai-chat-message-assistant-feedback');\n\n for (var i = 0; i < containers.length; i++) {\n var msgId = containers[i].getAttribute('data-message-id');\n var msg = this.messages.find(m => m.id === msgId);\n\n if (msg) {\n this.updateFeedbackIcons(containers[i], msg.userRating);\n }\n }\n },\n rateMessage(message, isPositive, event) {\n var sessionId = this.getSessionId();\n\n if (!sessionId || !message.id || !this.connection) {\n return;\n }\n\n // Toggle: clicking the same rating again clears it.\n var newRating = message.userRating === isPositive ? null : isPositive;\n message.userRating = newRating;\n\n // Find the feedback container by message ID for reliable DOM targeting.\n var feedbackContainer = this.$el.querySelector(\n '.ai-chat-message-assistant-feedback[data-message-id=\"' + message.id + '\"]'\n );\n\n this.updateFeedbackIcons(feedbackContainer, newRating);\n\n // Trigger spark animation after Font Awesome has re-processed icons.\n if (newRating !== null && feedbackContainer) {\n setTimeout(() => {\n var btnClass = isPositive ? '.rate-up-btn' : '.rate-down-btn';\n var btn = feedbackContainer.querySelector(btnClass);\n\n if (btn) {\n btn.classList.remove('spark-effect');\n void btn.offsetWidth;\n btn.classList.add('spark-effect');\n btn.addEventListener('animationend', function onEnd() {\n btn.removeEventListener('animationend', onEnd);\n btn.classList.remove('spark-effect');\n });\n }\n }, 50);\n }\n\n this.connection.invoke(\"RateMessage\", sessionId, message.id, isPositive).catch(function (err) {\n console.error('Failed to rate message:', err);\n });\n }\n },\n watch: {\n documents: {\n handler() {\n this.renderDocumentBar();\n if (widgetBehavior && typeof widgetBehavior.onDocumentsChanged === 'function') {\n widgetBehavior.onDocumentsChanged(this, this.documents, config);\n }\n },\n deep: true\n },\n isUploading() { this.renderDocumentBar(); },\n isDocumentOperationPending() { this.renderDocumentBar(); },\n isPlayingAudio() {\n // Reserved for future use — volume-based interrupt detection\n // no longer mutes tracks; browser echo cancellation handles echo.\n },\n copiedMessageIndex() {\n this.$nextTick(() => this.updateCopyButtons());\n },\n isConversationMode(active) {\n // Hide/show mic button.\n if (this.micButton) {\n this.micButton.style.display = active ? 'none' : (this.speechToTextEnabled ? '' : 'none');\n }\n\n // Hide/show send button.\n if (this.buttonElement) {\n this.buttonElement.style.display = active ? 'none' : '';\n }\n\n // Disable/enable textarea.\n if (this.inputElement) {\n this.inputElement.disabled = active;\n if (active) {\n this.inputElement.placeholder = '';\n }\n }\n }\n },\n mounted() {\n (async () => {\n await this.startConnection();\n const isInitialized = this.initializeApp();\n if (isInitialized && hasWidgetConfig && widgetBehavior && typeof widgetBehavior.onMounted === 'function') {\n widgetBehavior.onMounted(this, config);\n }\n\n this.$nextTick(() => {\n this.updateCopyButtons();\n refreshFontAwesomeIcons(this.$el);\n this.fontAwesomeObserver = observeFontAwesomeIcons(this.$el);\n });\n })();\n\n window.addEventListener('beforeunload', this.handleBeforeUnload);\n window.addEventListener('crestapps-ai-chat-stop-tts', this.handleExternalTtsStop);\n },\n beforeUnmount() {\n window.removeEventListener('beforeunload', this.handleBeforeUnload);\n window.removeEventListener('crestapps-ai-chat-stop-tts', this.handleExternalTtsStop);\n\n if (this.fontAwesomeObserver) {\n this.fontAwesomeObserver.disconnect();\n this.fontAwesomeObserver = null;\n }\n\n this.clearCopiedMessageState();\n this.stopAudio(false);\n\n if (this.stream) {\n this.stream.dispose();\n this.stream = null;\n }\n if (this.connection) {\n this.connection.stop();\n }\n\n if (widgetBehavior && typeof widgetBehavior.onBeforeUnmount === 'function') {\n widgetBehavior.onBeforeUnmount(this, config);\n }\n },\n template: config.messageTemplate\n };\n\n const app = Vue.createApp(appDefinition).mount(config.appElementSelector);\n\n if (widgetBehavior && typeof widgetBehavior.attach === 'function') {\n widgetBehavior.attach(app, config);\n }\n\n return app;\n };\n\n const autoInitializeSelector = '[data-coreai-chat-config],[data-coreai-chat-app-element-selector]';\n\n function getAttributeValue(element, attributeName) {\n const value = element.getAttribute(attributeName);\n return value === null || value === '' ? null : value;\n }\n\n function parseBooleanAttributeValue(value) {\n if (value === null || value === undefined) {\n return null;\n }\n\n if (typeof value === 'boolean') {\n return value;\n }\n\n const normalized = String(value).trim().toLowerCase();\n if (normalized === 'true') {\n return true;\n }\n\n if (normalized === 'false') {\n return false;\n }\n\n return null;\n }\n\n function parseJsonAttribute(element, attributeName, description) {\n const rawValue = getAttributeValue(element, attributeName);\n if (!rawValue) {\n return null;\n }\n\n try {\n return JSON.parse(rawValue);\n } catch (error) {\n console.error('Failed to parse ' + description + ' JSON.', error);\n return null;\n }\n }\n\n function buildConfigFromDataAttributes(element, options) {\n const settings = options || {};\n\n if (element.hasAttribute('data-coreai-chat-widget-container-selector') && settings.allowWidgetHost !== true) {\n return null;\n }\n\n const appElementSelector = getAttributeValue(element, 'data-coreai-chat-app-element-selector');\n if (!appElementSelector) {\n return null;\n }\n\n const config = {\n signalRHubUrl: getAttributeValue(element, 'data-coreai-chat-signalr-hub-url'),\n appElementSelector: appElementSelector,\n chatContainerElementSelector: getAttributeValue(element, 'data-coreai-chat-container-element-selector'),\n inputElementSelector: getAttributeValue(element, 'data-coreai-chat-input-element-selector'),\n sendButtonElementSelector: getAttributeValue(element, 'data-coreai-chat-send-button-element-selector'),\n placeholderElementSelector: getAttributeValue(element, 'data-coreai-chat-placeholder-element-selector'),\n messages: parseJsonAttribute(element, 'data-coreai-chat-messages', 'CoreAI chat messages') ?? undefined,\n chatMode: getAttributeValue(element, 'data-coreai-chat-mode'),\n micButtonElementSelector: getAttributeValue(element, 'data-coreai-chat-mic-button-element-selector'),\n conversationButtonElementSelector: getAttributeValue(element, 'data-coreai-chat-conversation-button-element-selector'),\n ttsVoiceName: getAttributeValue(element, 'data-coreai-chat-tts-voice-name'),\n documentBarSelector: getAttributeValue(element, 'data-coreai-chat-document-bar-selector'),\n uploadDocumentUrl: getAttributeValue(element, 'data-coreai-chat-upload-document-url'),\n removeDocumentUrl: getAttributeValue(element, 'data-coreai-chat-remove-document-url'),\n allowedExtensions: getAttributeValue(element, 'data-coreai-chat-allowed-extensions'),\n supportedExtensionsText: getAttributeValue(element, 'data-coreai-chat-supported-extensions-text'),\n existingDocuments: parseJsonAttribute(element, 'data-coreai-chat-existing-documents', 'CoreAI chat existing documents') ?? undefined,\n initialPrompt: getAttributeValue(element, 'data-coreai-chat-initial-prompt'),\n userLabel: getAttributeValue(element, 'data-coreai-chat-user-label'),\n assistantLabel: getAttributeValue(element, 'data-coreai-chat-assistant-label'),\n copyTitle: getAttributeValue(element, 'data-coreai-chat-copy-title'),\n copiedTitle: getAttributeValue(element, 'data-coreai-chat-copied-title'),\n };\n\n const booleanAttributes = {\n metricsEnabled: 'data-coreai-chat-metrics-enabled',\n textToSpeechEnabled: 'data-coreai-chat-text-to-speech-enabled',\n sessionDocumentsEnabled: 'data-coreai-chat-session-documents-enabled',\n singleResponseMode: 'data-coreai-chat-single-response-mode',\n };\n\n Object.keys(booleanAttributes).forEach(key => {\n const parsed = parseBooleanAttributeValue(getAttributeValue(element, booleanAttributes[key]));\n if (parsed !== null) {\n config[key] = parsed;\n }\n });\n\n return compactObject(config);\n }\n\n function buildConfigFromElement(element, options) {\n const jsonConfig = parseJsonAttribute(element, 'data-coreai-chat-config', 'CoreAI chat config');\n const attributeConfig = buildConfigFromDataAttributes(element, options);\n\n if (!jsonConfig && !attributeConfig) {\n return null;\n }\n\n return Object.assign({}, jsonConfig || {}, attributeConfig || {});\n }\n\n function initializeFromElement(element) {\n if (!element || element.dataset.coreAiChatInitialized === 'true') {\n return element ? element.__coreAIChatApp || null : null;\n }\n\n const config = buildConfigFromElement(element);\n if (!config) {\n return null;\n }\n\n const app = initialize(config);\n if (!app) {\n return null;\n }\n\n element.dataset.coreAiChatInitialized = 'true';\n element.__coreAIChatApp = app;\n\n return app;\n }\n\n function scanForAutoInitialization(root) {\n if (!root || typeof root.querySelectorAll !== 'function') {\n return;\n }\n\n if (typeof root.matches === 'function' && root.matches(autoInitializeSelector)) {\n initializeFromElement(root);\n }\n\n root.querySelectorAll(autoInitializeSelector).forEach(initializeFromElement);\n }\n\n function startAutoInitialization() {\n scanForAutoInitialization(document);\n\n if (typeof MutationObserver === 'undefined') {\n return;\n }\n\n const observer = new MutationObserver(mutations => {\n mutations.forEach(mutation => {\n mutation.addedNodes.forEach(node => {\n if (node && node.nodeType === 1) {\n scanForAutoInitialization(node);\n }\n });\n });\n });\n\n observer.observe(document.body, {\n childList: true,\n subtree: true,\n });\n }\n\n if (document.readyState === 'loading') {\n document.addEventListener('DOMContentLoaded', startAutoInitialization, { once: true });\n } else {\n startAutoInitialization();\n }\n\n return {\n initialize: initialize,\n initializeFromElement: initializeFromElement,\n buildConfigFromElement: buildConfigFromElement,\n };\n}();\n\n// Download chart as image via event delegation (DOMPurify strips inline onclick).\ndocument.addEventListener('click', function (e) {\n const btn = e.target.closest('.download-chart-btn');\n if (!btn) {\n return;\n }\n const chartId = btn.getAttribute('data-chart-id');\n const canvas = chartId ? document.getElementById(chartId) : null;\n if (!canvas) {\n console.error('Chart canvas not found:', chartId);\n return;\n }\n const link = document.createElement('a');\n link.download = 'chart-' + chartId + '.png';\n link.href = canvas.toDataURL('image/png');\n link.click();\n});\n\n// Intercept download clicks for data-URI images and convert to blob downloads.\ndocument.addEventListener('click', function (e) {\n const link = e.target.closest('.ai-download-image');\n if (!link) {\n return;\n }\n\n const container = link.closest('.generated-image-container');\n const img = container?.querySelector('img');\n if (!img) {\n return;\n }\n\n const src = img.src;\n if (!src || !src.startsWith('data:')) {\n return; // Normal URL – let the default behaviour handle it.\n }\n\n e.preventDefault();\n\n fetch(src)\n .then(function (res) { return res.blob(); })\n .then(function (blob) {\n const url = URL.createObjectURL(blob);\n const a = document.createElement('a');\n a.href = url;\n a.download = link.getAttribute('download') || 'generated-image.png';\n document.body.appendChild(a);\n a.click();\n document.body.removeChild(a);\n setTimeout(function () { URL.revokeObjectURL(url); }, 100);\n })\n .catch(function (err) { console.error('Failed to download image:', err); });\n});\n"]} diff --git a/src/Startup/CrestApps.Core.Blazor.Web/Areas/AIChat/Endpoints/CreateChatSessionEndpoint.cs b/src/Startup/CrestApps.Core.Blazor.Web/Areas/AIChat/Endpoints/CreateChatSessionEndpoint.cs index eaa8f1ed..c6669806 100644 --- a/src/Startup/CrestApps.Core.Blazor.Web/Areas/AIChat/Endpoints/CreateChatSessionEndpoint.cs +++ b/src/Startup/CrestApps.Core.Blazor.Web/Areas/AIChat/Endpoints/CreateChatSessionEndpoint.cs @@ -3,6 +3,7 @@ using CrestApps.Core.AI.Profiles; using CrestApps.Core.Filters; using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.Options; namespace CrestApps.Core.Blazor.Web.Areas.AIChat.Endpoints; @@ -10,8 +11,11 @@ internal static class CreateChatSessionEndpoint { public static IEndpointRouteBuilder AddCreateChatSessionEndpoint(this IEndpointRouteBuilder builder) { + var endpointRateLimitingOptions = builder.ServiceProvider.GetRequiredService>().Value; + _ = builder.MapPost("api/chat/create-session", HandleAsync) .AddEndpointFilter() + .RequireRateLimiting(endpointRateLimitingOptions.AnonymousSessionStartPolicyName) .RequireAuthorization() .DisableAntiforgery(); diff --git a/src/Startup/CrestApps.Core.Blazor.Web/Areas/AIChat/Hubs/AIChatHub.cs b/src/Startup/CrestApps.Core.Blazor.Web/Areas/AIChat/Hubs/AIChatHub.cs index 1704d56b..947f40a7 100644 --- a/src/Startup/CrestApps.Core.Blazor.Web/Areas/AIChat/Hubs/AIChatHub.cs +++ b/src/Startup/CrestApps.Core.Blazor.Web/Areas/AIChat/Hubs/AIChatHub.cs @@ -2,6 +2,8 @@ using CrestApps.Core.AI.Chat.Services; using CrestApps.Core.AI.Models; using CrestApps.Core.AI.ResponseHandling; +using CrestApps.Core.Blazor.Web.Models; +using CrestApps.Core.Startup.Shared.Services; using Microsoft.AspNetCore.Authorization; namespace CrestApps.Core.Blazor.Web.Areas.AIChat.Hubs; @@ -10,7 +12,7 @@ namespace CrestApps.Core.Blazor.Web.Areas.AIChat.Hubs; /// Blazor-specific AI chat hub. Inherits all behavior from . /// Uses constructor-injected services directly (no ShellScope needed). /// -[Authorize] +[AllowAnonymous] public sealed class AIChatHub : AIChatHubCore { public AIChatHub( @@ -21,6 +23,20 @@ public AIChatHub( { } + /// + protected override Task AuthorizeProfileAsync(IServiceProvider services, AIProfile profile) + { + ArgumentNullException.ThrowIfNull(services); + ArgumentNullException.ThrowIfNull(profile); + + var widgetSettings = services.GetRequiredService().Get(); + + return Task.FromResult(AIChatWidgetAccessEvaluator.CanAccessProfile( + Context.User, + widgetSettings.ProfileId, + profile.ItemId)); + } + protected override void CollectStreamingReferences( IServiceProvider services, ChatResponseHandlerContext handlerContext, diff --git a/src/Startup/CrestApps.Core.Blazor.Web/Components/Layout/MainLayout.razor b/src/Startup/CrestApps.Core.Blazor.Web/Components/Layout/MainLayout.razor index 53ab6e91..89b3e01c 100644 --- a/src/Startup/CrestApps.Core.Blazor.Web/Components/Layout/MainLayout.razor +++ b/src/Startup/CrestApps.Core.Blazor.Web/Components/Layout/MainLayout.razor @@ -59,8 +59,4 @@ - - - - - + diff --git a/src/Startup/CrestApps.Core.Blazor.Web/Components/Pages/Admin/Settings/Index.razor b/src/Startup/CrestApps.Core.Blazor.Web/Components/Pages/Admin/Settings/Index.razor index 4370958f..3023cf55 100644 --- a/src/Startup/CrestApps.Core.Blazor.Web/Components/Pages/Admin/Settings/Index.razor +++ b/src/Startup/CrestApps.Core.Blazor.Web/Components/Pages/Admin/Settings/Index.razor @@ -361,6 +361,57 @@ else
Controls the minimum risk level at which prompts are blocked. Lower thresholds are stricter.
+ +
+ + +
Choose whether anonymous abuse controls should avoid remote-address data, store only a salted hash, store the raw address for operator-managed blocklists and investigations, or encrypt the address at rest while still using a hash for throttling.
+
+ +
+ + + @if (_errors.TryGetValue(nameof(_model.SecurityMaxMessagesPerWindow), out var maxMessagesErr)) + { + @maxMessagesErr + } +
Anonymous and authenticated chat prompts are throttled after this many messages. Set to 0 to disable message throttling.
+
+ +
+ + + @if (_errors.TryGetValue(nameof(_model.SecurityRateLimitWindowSeconds), out var messageWindowErr)) + { + @messageWindowErr + } +
Determines how long message-throttle counters remain active.
+
+ +
+ + + @if (_errors.TryGetValue(nameof(_model.SecurityMaxAnonymousSessionsPerWindow), out var maxSessionsErr)) + { + @maxSessionsErr + } +
Limits how many new anonymous widget sessions can be started from the same visitor/IP bucket. Set to 0 to disable session-start throttling.
+
+ +
+ + + @if (_errors.TryGetValue(nameof(_model.SecurityAnonymousSessionRateLimitWindowSeconds), out var anonymousWindowErr)) + { + @anonymousWindowErr + } +
Determines how long anonymous session-start counters remain active for the ASP.NET Core and hub session throttles.
+
} @@ -784,6 +835,7 @@ else var paginationSettings = SiteSettings.Get(); var adminWidgetSettings = SiteSettings.Get(); var promptSecuritySettings = SiteSettings.Get(); + var visitorIdentitySettings = SiteSettings.Get(); _model = new SettingsViewModel { @@ -847,6 +899,11 @@ else SecurityEnableAuditLogging = promptSecuritySettings.EnableAuditLogging, SecurityMaxPromptLength = promptSecuritySettings.MaxPromptLength, SecurityBlockingThreshold = promptSecuritySettings.BlockingThreshold, + SecurityMaxMessagesPerWindow = promptSecuritySettings.MaxMessagesPerWindow, + SecurityRateLimitWindowSeconds = (int)Math.Round(promptSecuritySettings.RateLimitWindow.TotalSeconds), + SecurityMaxAnonymousSessionsPerWindow = promptSecuritySettings.MaxAnonymousSessionsPerWindow, + SecurityAnonymousSessionRateLimitWindowSeconds = (int)Math.Round(promptSecuritySettings.AnonymousSessionRateLimitWindow.TotalSeconds), + SecurityRemoteAddressMode = visitorIdentitySettings.RemoteAddressMode, }; await PopulateDropdownsAsync(); @@ -1007,6 +1064,26 @@ else _errors[nameof(_model.SecurityMaxPromptLength)] = "Must be between 100 and 100,000."; } + if (_model.SecurityMaxMessagesPerWindow < 0 || _model.SecurityMaxMessagesPerWindow > 1000) + { + _errors[nameof(_model.SecurityMaxMessagesPerWindow)] = "Must be between 0 and 1,000."; + } + + if (_model.SecurityRateLimitWindowSeconds < 1 || _model.SecurityRateLimitWindowSeconds > 86400) + { + _errors[nameof(_model.SecurityRateLimitWindowSeconds)] = "Must be between 1 and 86,400 seconds."; + } + + if (_model.SecurityMaxAnonymousSessionsPerWindow < 0 || _model.SecurityMaxAnonymousSessionsPerWindow > 500) + { + _errors[nameof(_model.SecurityMaxAnonymousSessionsPerWindow)] = "Must be between 0 and 500."; + } + + if (_model.SecurityAnonymousSessionRateLimitWindowSeconds < 1 || _model.SecurityAnonymousSessionRateLimitWindowSeconds > 86400) + { + _errors[nameof(_model.SecurityAnonymousSessionRateLimitWindowSeconds)] = "Must be between 1 and 86,400 seconds."; + } + if (!string.IsNullOrWhiteSpace(_model.AdminWidgetPrimaryColor) && !Regex.IsMatch( _model.AdminWidgetPrimaryColor, @@ -1181,8 +1258,16 @@ else EnableAuditLogging = _model.SecurityEnabled && _model.SecurityEnableAuditLogging, MaxPromptLength = _model.SecurityMaxPromptLength, BlockingThreshold = _model.SecurityBlockingThreshold, + MaxMessagesPerWindow = _model.SecurityMaxMessagesPerWindow, + RateLimitWindow = TimeSpan.FromSeconds(_model.SecurityRateLimitWindowSeconds), + MaxAnonymousSessionsPerWindow = _model.SecurityMaxAnonymousSessionsPerWindow, + AnonymousSessionRateLimitWindow = TimeSpan.FromSeconds(_model.SecurityAnonymousSessionRateLimitWindowSeconds), }); + var visitorIdentitySettings = SiteSettings.Get(); + visitorIdentitySettings.RemoteAddressMode = _model.SecurityRemoteAddressMode; + SiteSettings.Set(visitorIdentitySettings); + await SiteSettings.SaveChangesAsync(); await SettingsChangedNotifier.NotifyAsync(); diff --git a/src/Startup/CrestApps.Core.Blazor.Web/Components/Shared/ChatWidget.razor b/src/Startup/CrestApps.Core.Blazor.Web/Components/Shared/ChatWidget.razor index 7830e693..65914a81 100644 --- a/src/Startup/CrestApps.Core.Blazor.Web/Components/Shared/ChatWidget.razor +++ b/src/Startup/CrestApps.Core.Blazor.Web/Components/Shared/ChatWidget.razor @@ -51,7 +51,6 @@ data-coreai-chat-input-element-selector="#widget-chat-input" data-coreai-chat-send-button-element-selector="#widget-send-btn" data-coreai-chat-placeholder-element-selector="#widget-placeholder" - data-coreai-chat-auto-create-session="true" data-coreai-chat-metrics-enabled="@_metricsEnabled.ToString().ToLowerInvariant()" data-coreai-chat-mode="@_chatMode" data-coreai-chat-mic-button-element-selector="#widget-mic-btn" diff --git a/src/Startup/CrestApps.Core.Blazor.Web/Program.cs b/src/Startup/CrestApps.Core.Blazor.Web/Program.cs index 1b2a8d40..8618a043 100644 --- a/src/Startup/CrestApps.Core.Blazor.Web/Program.cs +++ b/src/Startup/CrestApps.Core.Blazor.Web/Program.cs @@ -71,6 +71,7 @@ .AddInteractiveServerComponents(); builder.Services.AddHttpContextAccessor(); builder.Services.AddScoped(); +builder.Services.AddSharedAIChatProtection(); // ============================================================================= // 5. AUTHENTICATION & AUTHORIZATION @@ -195,6 +196,7 @@ app.UseHttpsRedirection() .UseStaticFiles() .UseRouting() + .UseSharedAIChatProtection() .UseAuthentication() .UseAuthorization() .UseAntiforgery(); @@ -245,6 +247,7 @@ await next(); }); }); + app.MapHub("/hubs/ai-chat"); app.MapHub("/hubs/chat-interaction"); app.MapMcp("mcp"); diff --git a/src/Startup/CrestApps.Core.Blazor.Web/ViewModels/SettingsViewModel.cs b/src/Startup/CrestApps.Core.Blazor.Web/ViewModels/SettingsViewModel.cs index a9c0ffa7..880c4353 100644 --- a/src/Startup/CrestApps.Core.Blazor.Web/ViewModels/SettingsViewModel.cs +++ b/src/Startup/CrestApps.Core.Blazor.Web/ViewModels/SettingsViewModel.cs @@ -126,6 +126,16 @@ public sealed class SettingsViewModel public PromptRiskLevel SecurityBlockingThreshold { get; set; } = PromptRiskLevel.High; + public int SecurityMaxMessagesPerWindow { get; set; } = 20; + + public int SecurityRateLimitWindowSeconds { get; set; } = 60; + + public int SecurityMaxAnonymousSessionsPerWindow { get; set; } = 5; + + public int SecurityAnonymousSessionRateLimitWindowSeconds { get; set; } = 600; + + public AIVisitorRemoteAddressMode SecurityRemoteAddressMode { get; set; } = AIVisitorRemoteAddressMode.Hashed; + // Dropdown items populated at load time. public List> ChatDeployments { get; set; } = []; diff --git a/src/Startup/CrestApps.Core.Mvc.Web/Areas/AIChat/Endpoints/CreateChatSessionEndpoint.cs b/src/Startup/CrestApps.Core.Mvc.Web/Areas/AIChat/Endpoints/CreateChatSessionEndpoint.cs index a0abd8a6..4cb094ac 100644 --- a/src/Startup/CrestApps.Core.Mvc.Web/Areas/AIChat/Endpoints/CreateChatSessionEndpoint.cs +++ b/src/Startup/CrestApps.Core.Mvc.Web/Areas/AIChat/Endpoints/CreateChatSessionEndpoint.cs @@ -3,6 +3,7 @@ using CrestApps.Core.AI.Profiles; using CrestApps.Core.Filters; using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.Options; namespace CrestApps.Core.Mvc.Web.Areas.AIChat.Endpoints; @@ -10,8 +11,11 @@ internal static class CreateChatSessionEndpoint { public static IEndpointRouteBuilder AddCreateChatSessionEndpoint(this IEndpointRouteBuilder builder) { + var endpointRateLimitingOptions = builder.ServiceProvider.GetRequiredService>().Value; + _ = builder.MapPost("api/chat/create-session", HandleAsync) .AddEndpointFilter() + .RequireRateLimiting(endpointRateLimitingOptions.AnonymousSessionStartPolicyName) .RequireAuthorization() .DisableAntiforgery(); diff --git a/src/Startup/CrestApps.Core.Mvc.Web/Areas/AIChat/Hubs/AIChatHub.cs b/src/Startup/CrestApps.Core.Mvc.Web/Areas/AIChat/Hubs/AIChatHub.cs index 8a82d906..39a53553 100644 --- a/src/Startup/CrestApps.Core.Mvc.Web/Areas/AIChat/Hubs/AIChatHub.cs +++ b/src/Startup/CrestApps.Core.Mvc.Web/Areas/AIChat/Hubs/AIChatHub.cs @@ -2,6 +2,8 @@ using CrestApps.Core.AI.Chat.Services; using CrestApps.Core.AI.Models; using CrestApps.Core.AI.ResponseHandling; +using CrestApps.Core.Mvc.Web.Areas.AIChat.Models; +using CrestApps.Core.Startup.Shared.Services; using Microsoft.AspNetCore.Authorization; namespace CrestApps.Core.Mvc.Web.Areas.AIChat.Hubs; @@ -10,7 +12,7 @@ namespace CrestApps.Core.Mvc.Web.Areas.AIChat.Hubs; /// MVC-specific AI chat hub. Inherits all behavior from . /// Uses constructor-injected services directly (no ShellScope needed). /// -[Authorize] +[AllowAnonymous] public sealed class AIChatHub : AIChatHubCore { public AIChatHub( @@ -21,6 +23,20 @@ public AIChatHub( { } + /// + protected override Task AuthorizeProfileAsync(IServiceProvider services, AIProfile profile) + { + ArgumentNullException.ThrowIfNull(services); + ArgumentNullException.ThrowIfNull(profile); + + var widgetSettings = services.GetRequiredService().Get(); + + return Task.FromResult(AIChatWidgetAccessEvaluator.CanAccessProfile( + Context.User, + widgetSettings.ProfileId, + profile.ItemId)); + } + protected override void CollectStreamingReferences( IServiceProvider services, ChatResponseHandlerContext handlerContext, diff --git a/src/Startup/CrestApps.Core.Mvc.Web/Areas/AIChat/Views/Shared/_ChatWidget.cshtml b/src/Startup/CrestApps.Core.Mvc.Web/Areas/AIChat/Views/Shared/_ChatWidget.cshtml index 7f7d4262..f71e62cc 100644 --- a/src/Startup/CrestApps.Core.Mvc.Web/Areas/AIChat/Views/Shared/_ChatWidget.cshtml +++ b/src/Startup/CrestApps.Core.Mvc.Web/Areas/AIChat/Views/Shared/_ChatWidget.cshtml @@ -117,7 +117,6 @@ data-coreai-chat-input-element-selector="#widget-chat-input" data-coreai-chat-send-button-element-selector="#widget-send-btn" data-coreai-chat-placeholder-element-selector="#widget-placeholder" - data-coreai-chat-auto-create-session="true" data-coreai-chat-metrics-enabled="@profile.enableSessionMetrics.ToString().ToLowerInvariant()" data-coreai-chat-mode="@profile.chatMode" data-coreai-chat-mic-button-element-selector="#widget-mic-btn" diff --git a/src/Startup/CrestApps.Core.Mvc.Web/Areas/Admin/Controllers/SettingsController.cs b/src/Startup/CrestApps.Core.Mvc.Web/Areas/Admin/Controllers/SettingsController.cs index 87c9799b..0a22662a 100644 --- a/src/Startup/CrestApps.Core.Mvc.Web/Areas/Admin/Controllers/SettingsController.cs +++ b/src/Startup/CrestApps.Core.Mvc.Web/Areas/Admin/Controllers/SettingsController.cs @@ -77,6 +77,7 @@ public async Task Index() var adminWidgetSettings = _siteSettings.Get(); var chatSessionProcessingSettings = _siteSettings.Get(); var promptSecuritySettings = _siteSettings.Get(); + var visitorIdentitySettings = _siteSettings.Get(); var model = new SettingsViewModel { @@ -137,6 +138,11 @@ public async Task Index() SecurityEnableAuditLogging = promptSecuritySettings.EnableAuditLogging, SecurityMaxPromptLength = promptSecuritySettings.MaxPromptLength, SecurityBlockingThreshold = promptSecuritySettings.BlockingThreshold, + SecurityMaxMessagesPerWindow = promptSecuritySettings.MaxMessagesPerWindow, + SecurityRateLimitWindowSeconds = (int)Math.Round(promptSecuritySettings.RateLimitWindow.TotalSeconds), + SecurityMaxAnonymousSessionsPerWindow = promptSecuritySettings.MaxAnonymousSessionsPerWindow, + SecurityAnonymousSessionRateLimitWindowSeconds = (int)Math.Round(promptSecuritySettings.AnonymousSessionRateLimitWindow.TotalSeconds), + SecurityRemoteAddressMode = visitorIdentitySettings.RemoteAddressMode, }; await NormalizeDeploymentSelectorsAsync(model); @@ -206,6 +212,26 @@ public async Task Save(SettingsViewModel model) ModelState.AddModelError(nameof(model.SecurityMaxPromptLength), "Must be between 100 and 100,000."); } + if (model.SecurityMaxMessagesPerWindow < 0 || model.SecurityMaxMessagesPerWindow > 1000) + { + ModelState.AddModelError(nameof(model.SecurityMaxMessagesPerWindow), "Must be between 0 and 1,000."); + } + + if (model.SecurityRateLimitWindowSeconds < 1 || model.SecurityRateLimitWindowSeconds > 86400) + { + ModelState.AddModelError(nameof(model.SecurityRateLimitWindowSeconds), "Must be between 1 and 86,400 seconds."); + } + + if (model.SecurityMaxAnonymousSessionsPerWindow < 0 || model.SecurityMaxAnonymousSessionsPerWindow > 500) + { + ModelState.AddModelError(nameof(model.SecurityMaxAnonymousSessionsPerWindow), "Must be between 0 and 500."); + } + + if (model.SecurityAnonymousSessionRateLimitWindowSeconds < 1 || model.SecurityAnonymousSessionRateLimitWindowSeconds > 86400) + { + ModelState.AddModelError(nameof(model.SecurityAnonymousSessionRateLimitWindowSeconds), "Must be between 1 and 86,400 seconds."); + } + if (!string.IsNullOrWhiteSpace(model.AdminWidgetPrimaryColor) && !Regex.IsMatch( model.AdminWidgetPrimaryColor, @@ -388,8 +414,16 @@ public async Task Save(SettingsViewModel model) EnableAuditLogging = model.SecurityEnabled && model.SecurityEnableAuditLogging, MaxPromptLength = model.SecurityMaxPromptLength, BlockingThreshold = model.SecurityBlockingThreshold, + MaxMessagesPerWindow = model.SecurityMaxMessagesPerWindow, + RateLimitWindow = TimeSpan.FromSeconds(model.SecurityRateLimitWindowSeconds), + MaxAnonymousSessionsPerWindow = model.SecurityMaxAnonymousSessionsPerWindow, + AnonymousSessionRateLimitWindow = TimeSpan.FromSeconds(model.SecurityAnonymousSessionRateLimitWindowSeconds), }); + var visitorIdentitySettings = _siteSettings.Get(); + visitorIdentitySettings.RemoteAddressMode = model.SecurityRemoteAddressMode; + _siteSettings.Set(visitorIdentitySettings); + // Persist everything to disk in a single atomic file write. await _siteSettings.SaveChangesAsync(); diff --git a/src/Startup/CrestApps.Core.Mvc.Web/Areas/Admin/ViewModels/SettingsViewModel.cs b/src/Startup/CrestApps.Core.Mvc.Web/Areas/Admin/ViewModels/SettingsViewModel.cs index a80e5de8..8d5b8c16 100644 --- a/src/Startup/CrestApps.Core.Mvc.Web/Areas/Admin/ViewModels/SettingsViewModel.cs +++ b/src/Startup/CrestApps.Core.Mvc.Web/Areas/Admin/ViewModels/SettingsViewModel.cs @@ -131,6 +131,16 @@ public sealed class SettingsViewModel public PromptRiskLevel SecurityBlockingThreshold { get; set; } = PromptRiskLevel.High; + public int SecurityMaxMessagesPerWindow { get; set; } = 20; + + public int SecurityRateLimitWindowSeconds { get; set; } = 60; + + public int SecurityMaxAnonymousSessionsPerWindow { get; set; } = 5; + + public int SecurityAnonymousSessionRateLimitWindowSeconds { get; set; } = 600; + + public AIVisitorRemoteAddressMode SecurityRemoteAddressMode { get; set; } = AIVisitorRemoteAddressMode.Hashed; + [BindNever] public string CopilotCallbackUrl { get; set; } diff --git a/src/Startup/CrestApps.Core.Mvc.Web/Areas/Admin/Views/Settings/Index.cshtml b/src/Startup/CrestApps.Core.Mvc.Web/Areas/Admin/Views/Settings/Index.cshtml index 0e9b8308..80899571 100644 --- a/src/Startup/CrestApps.Core.Mvc.Web/Areas/Admin/Views/Settings/Index.cshtml +++ b/src/Startup/CrestApps.Core.Mvc.Web/Areas/Admin/Views/Settings/Index.cshtml @@ -1,5 +1,6 @@ @using CrestApps.Core.AI.Claude.Models @using CrestApps.Core.AI.Documents.Models +@using CrestApps.Core.AI.Security @model CrestApps.Core.Mvc.Web.Areas.Admin.ViewModels.SettingsViewModel @{ ViewData["Title"] = "AI Settings"; @@ -274,6 +275,45 @@
Controls the minimum risk level at which prompts are blocked. Lower thresholds are stricter.
+ +
+ + +
Choose whether anonymous abuse controls should avoid remote-address data, store only a salted hash, store the raw address for operator-managed blocklists and investigations, or encrypt the address at rest while still using a hash for throttling.
+
+ +
+ + + +
Anonymous and authenticated chat prompts are throttled after this many messages. Set to 0 to disable message throttling.
+
+ +
+ + + +
Determines how long message-throttle counters remain active.
+
+ +
+ + + +
Limits how many new anonymous widget sessions can be started from the same visitor/IP bucket. Set to 0 to disable session-start throttling.
+
+ +
+ + + +
Determines how long anonymous session-start counters remain active for the ASP.NET Core and hub session throttles.
+
diff --git a/src/Startup/CrestApps.Core.Mvc.Web/Program.cs b/src/Startup/CrestApps.Core.Mvc.Web/Program.cs index c25fe22b..beaaf3a4 100644 --- a/src/Startup/CrestApps.Core.Mvc.Web/Program.cs +++ b/src/Startup/CrestApps.Core.Mvc.Web/Program.cs @@ -80,6 +80,7 @@ .AddCrestAppsStoreCommitterFilter(); builder.Services.AddHttpContextAccessor(); +builder.Services.AddSharedAIChatProtection(); // ============================================================================= // 3. CRESTAPPS FRAMEWORK COMPOSITION @@ -203,6 +204,7 @@ app.UseHttpsRedirection() .UseStaticFiles() .UseRouting() + .UseSharedAIChatProtection() .UseAuthentication() .UseAuthorization(); diff --git a/src/Startup/CrestApps.Core.Mvc.Web/Views/Shared/_Layout.cshtml b/src/Startup/CrestApps.Core.Mvc.Web/Views/Shared/_Layout.cshtml index 287e27b8..69dcdaec 100644 --- a/src/Startup/CrestApps.Core.Mvc.Web/Views/Shared/_Layout.cshtml +++ b/src/Startup/CrestApps.Core.Mvc.Web/Views/Shared/_Layout.cshtml @@ -182,7 +182,7 @@ @await RenderSectionAsync("Scripts", required: false) @await Html.PartialAsync("_ToastNotifications") - @if (User.Identity.IsAuthenticated && !string.Equals(ViewContext.RouteData.Values["area"]?.ToString(), "AIChat", StringComparison.OrdinalIgnoreCase)) + @if (!string.Equals(ViewContext.RouteData.Values["area"]?.ToString(), "AIChat", StringComparison.OrdinalIgnoreCase)) { @await Html.PartialAsync("~/Areas/AIChat/Views/Shared/_ChatWidget.cshtml") } diff --git a/src/Startup/CrestApps.Core.Startup.Shared/Services/AIChatProtectionExtensions.cs b/src/Startup/CrestApps.Core.Startup.Shared/Services/AIChatProtectionExtensions.cs new file mode 100644 index 00000000..062534d3 --- /dev/null +++ b/src/Startup/CrestApps.Core.Startup.Shared/Services/AIChatProtectionExtensions.cs @@ -0,0 +1,133 @@ +using System.Threading.RateLimiting; +using CrestApps.Core.AI.Chat; +using CrestApps.Core.AI.Security; +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.RateLimiting; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Options; + +namespace CrestApps.Core.Startup.Shared.Services; + +/// +/// Configures shared visitor-tracking and endpoint protection for AI chat sample hosts. +/// +public static class AIChatProtectionExtensions +{ + /// + /// Adds the shared AI chat rate-limit policies used by the sample hosts. + /// + /// The service collection. + public static IServiceCollection AddSharedAIChatProtection(this IServiceCollection services) + { + ArgumentNullException.ThrowIfNull(services); + + services.AddOptions(); + services.AddRateLimiter(); + services.AddSingleton, ConfigureAIChatEndpointRateLimiterOptions>(); + + return services; + } + + /// + /// Adds the shared AI chat middleware used by the sample hosts. + /// + /// The application builder. + public static IApplicationBuilder UseSharedAIChatProtection(this IApplicationBuilder app) + { + ArgumentNullException.ThrowIfNull(app); + + return app.UseAIAnonymousVisitorCookie() + .UseRateLimiter(); + } +} + +/// +/// Configures the shared ASP.NET Core rate-limiter policies used by the sample hosts. +/// +public sealed class ConfigureAIChatEndpointRateLimiterOptions : IConfigureOptions +{ + private readonly IOptions _endpointRateLimitingOptions; + + /// + /// Initializes a new instance of the class. + /// + /// The shared AI chat endpoint rate-limiting options. + public ConfigureAIChatEndpointRateLimiterOptions(IOptions endpointRateLimitingOptions) + { + _endpointRateLimitingOptions = endpointRateLimitingOptions; + } + + /// + /// Configures the ASP.NET Core rate-limiter options for AI chat sample hosts. + /// + /// The rate-limiter options to configure. + public void Configure(RateLimiterOptions options) + { + ArgumentNullException.ThrowIfNull(options); + + var endpointOptions = _endpointRateLimitingOptions.Value; + + options.OnRejected = static (context, cancellationToken) => + { + if (context.HttpContext.Response.HasStarted) + { + return ValueTask.CompletedTask; + } + + var endpointOptions = context.HttpContext.RequestServices.GetRequiredService>().Value; + context.HttpContext.Response.StatusCode = endpointOptions.RejectionStatusCode; + + return new ValueTask(context.HttpContext.Response.WriteAsJsonAsync( + new + { + error = endpointOptions.AnonymousSessionStartErrorMessage, + }, + cancellationToken: cancellationToken)); + }; + + options.GlobalLimiter = null; + options.RejectionStatusCode = endpointOptions.RejectionStatusCode; + + options.AddPolicy(endpointOptions.AnonymousSessionStartPolicyName, static httpContext => + { + var endpointOptions = httpContext.RequestServices.GetRequiredService>().Value; + + if (!endpointOptions.RegisterAnonymousSessionStartPolicy) + { + return RateLimitPartition.GetNoLimiter("disabled"); + } + + var promptSecurityOptions = httpContext.RequestServices.GetRequiredService>().CurrentValue; + + if (promptSecurityOptions.MaxAnonymousSessionsPerWindow <= 0 || + httpContext.User.Identity?.IsAuthenticated == true) + { + return RateLimitPartition.GetNoLimiter("disabled"); + } + + var rateLimitingOptions = httpContext.RequestServices.GetRequiredService>().Value; + var visitorIdentityResolver = httpContext.RequestServices.GetRequiredService(); + var visitorIdentity = visitorIdentityResolver.Resolve(); + var context = new PromptSecurityContext + { + User = httpContext.User, + VisitorId = visitorIdentity.VisitorId, + RemoteAddress = visitorIdentity.RemoteAddress, + RemoteAddressHash = visitorIdentity.RemoteAddressHash, + }; + var keys = ChatRateLimitKeyResolver.ResolveAnonymousSessionStartKeys(context, rateLimitingOptions); + var partitionKey = keys.Count > 0 ? string.Join("|", keys.OrderBy(static key => key, StringComparer.Ordinal)) : "anonymous"; + + return RateLimitPartition.GetFixedWindowLimiter( + partitionKey, + _ => new FixedWindowRateLimiterOptions + { + PermitLimit = promptSecurityOptions.MaxAnonymousSessionsPerWindow, + Window = promptSecurityOptions.AnonymousSessionRateLimitWindow, + QueueLimit = 0, + AutoReplenishment = true, + }); + }); + } +} diff --git a/src/Startup/CrestApps.Core.Startup.Shared/Services/AIChatWidgetAccessEvaluator.cs b/src/Startup/CrestApps.Core.Startup.Shared/Services/AIChatWidgetAccessEvaluator.cs new file mode 100644 index 00000000..6e28c76c --- /dev/null +++ b/src/Startup/CrestApps.Core.Startup.Shared/Services/AIChatWidgetAccessEvaluator.cs @@ -0,0 +1,32 @@ +using System.Security.Claims; + +namespace CrestApps.Core.Startup.Shared.Services; + +/// +/// Evaluates whether a caller can access the sample AI chat widget profile. +/// +public static class AIChatWidgetAccessEvaluator +{ + /// + /// Determines whether the current caller can access the requested chat profile. + /// + /// The current caller. + /// The profile configured for the sample widget. + /// The requested chat profile identifier. + /// when access should be allowed; otherwise . + public static bool CanAccessProfile( + ClaimsPrincipal user, + string widgetProfileId, + string requestedProfileId) + { + ArgumentNullException.ThrowIfNull(user); + + if (user.Identity?.IsAuthenticated == true) + { + return true; + } + + return !string.IsNullOrWhiteSpace(widgetProfileId) && + string.Equals(widgetProfileId, requestedProfileId, StringComparison.Ordinal); + } +} diff --git a/src/Startup/CrestApps.Core.Startup.Shared/Services/SharedWebApplicationBuilderExtensions.cs b/src/Startup/CrestApps.Core.Startup.Shared/Services/SharedWebApplicationBuilderExtensions.cs index 302c4ae2..9451ad39 100644 --- a/src/Startup/CrestApps.Core.Startup.Shared/Services/SharedWebApplicationBuilderExtensions.cs +++ b/src/Startup/CrestApps.Core.Startup.Shared/Services/SharedWebApplicationBuilderExtensions.cs @@ -78,6 +78,7 @@ public static IServiceCollection AddSharedSiteSettings(this IServiceCollection s services.AddSingleton, SiteSettingsConfigureAIDataSourceOptions>(); services.AddSingleton, SiteSettingsConfigureChatInteractionMemoryOptions>(); services.AddSingleton, SiteSettingsConfigureDefaultDeploymentOptions>(); + services.AddSingleton, SiteSettingsConfigureStoredOptions>(); services.AddSingleton, SiteSettingsConfigureStoredOptions>(); return services; diff --git a/src/Stores/CrestApps.Core.Data.EntityCore/ServiceCollectionExtensions.cs b/src/Stores/CrestApps.Core.Data.EntityCore/ServiceCollectionExtensions.cs index 37a68d5a..bf1ba2aa 100644 --- a/src/Stores/CrestApps.Core.Data.EntityCore/ServiceCollectionExtensions.cs +++ b/src/Stores/CrestApps.Core.Data.EntityCore/ServiceCollectionExtensions.cs @@ -9,6 +9,7 @@ using CrestApps.Core.AI.Memory; using CrestApps.Core.AI.Models; using CrestApps.Core.AI.Profiles; +using CrestApps.Core.AI.Security; using CrestApps.Core.Builders; using CrestApps.Core.Data.EntityCore.Services; using CrestApps.Core.Infrastructure.Indexing; @@ -196,6 +197,7 @@ public static IServiceCollection AddCoreAIChatSessionStoresEntityCore(this IServ { ArgumentNullException.ThrowIfNull(services); + services.TryAddSingleton(); services.Replace(ServiceDescriptor.Scoped()); services.Replace(ServiceDescriptor.Scoped()); services.Replace(ServiceDescriptor.Scoped()); diff --git a/src/Stores/CrestApps.Core.Data.EntityCore/Services/EntityCoreAIChatSessionManager.cs b/src/Stores/CrestApps.Core.Data.EntityCore/Services/EntityCoreAIChatSessionManager.cs index 551f97d3..e8fe1db5 100644 --- a/src/Stores/CrestApps.Core.Data.EntityCore/Services/EntityCoreAIChatSessionManager.cs +++ b/src/Stores/CrestApps.Core.Data.EntityCore/Services/EntityCoreAIChatSessionManager.cs @@ -4,16 +4,17 @@ using CrestApps.Core.AI.Documents; using CrestApps.Core.AI.Models; using CrestApps.Core.AI.ResponseHandling; +using CrestApps.Core.AI.Security; using CrestApps.Core.Data.EntityCore.Models; using Microsoft.AspNetCore.Http; using Microsoft.EntityFrameworkCore; -using Microsoft.Extensions.AI; namespace CrestApps.Core.Data.EntityCore.Services; public sealed class EntityCoreAIChatSessionManager : IAIChatSessionManager { private readonly IHttpContextAccessor _httpContextAccessor; + private readonly IAIVisitorIdentityResolver _visitorIdentityResolver; private readonly CrestAppsEntityDbContext _dbContext; private readonly IEnumerable _documentCleanupServices; private readonly TimeProvider _timeProvider; @@ -27,11 +28,13 @@ public sealed class EntityCoreAIChatSessionManager : IAIChatSessionManager /// The time provider. public EntityCoreAIChatSessionManager( IHttpContextAccessor httpContextAccessor, + IAIVisitorIdentityResolver visitorIdentityResolver, CrestAppsEntityDbContext dbContext, IEnumerable documentCleanupServices, TimeProvider timeProvider) { _httpContextAccessor = httpContextAccessor; + _visitorIdentityResolver = visitorIdentityResolver; _dbContext = dbContext; _documentCleanupServices = documentCleanupServices; _timeProvider = timeProvider; @@ -121,33 +124,21 @@ public Task NewAsync(AIProfile profile, NewAIChatSessionContext c }; var user = _httpContextAccessor.HttpContext?.User; var userId = user?.FindFirstValue(ClaimTypes.NameIdentifier) ?? user?.Identity?.Name; + var visitorIdentity = _visitorIdentityResolver.Resolve(); + session.RemoteAddress = visitorIdentity.RemoteAddress; + session.RemoteAddressHash = visitorIdentity.RemoteAddressHash; if (!string.IsNullOrEmpty(userId)) { session.UserId = userId; } + else + { + session.ClientId = visitorIdentity.VisitorId; + } if (profile.Type == AIProfileType.Chat) { - if (profile.TryGet(out var profileMetadata) && !string.IsNullOrWhiteSpace(profileMetadata.InitialPrompt)) - { - // Stage the initial prompt directly in the change tracker so that SaveAsync - // commits both the session and this prompt atomically in a single transaction. - // If SaveAsync is never called, the scope disposes without committing and no - // orphaned prompt is persisted. - var prompt = new AIChatSessionPrompt - { - ItemId = UniqueId.GenerateId(), - SessionId = session.SessionId, - Role = ChatRole.Assistant, - Title = profile.PromptSubject, - Content = profileMetadata.InitialPrompt, - CreatedUtc = now, - }; - - _dbContext.CatalogRecords.Add(CatalogRecordFactory.Create(prompt)); - } - var handlerSettings = profile.GetOrCreateSettings(); if (!string.IsNullOrEmpty(handlerSettings.InitialResponseHandlerName)) diff --git a/src/Stores/CrestApps.Core.Data.YesSql/ServiceCollectionExtensions.cs b/src/Stores/CrestApps.Core.Data.YesSql/ServiceCollectionExtensions.cs index f5e51415..d67d4b6a 100644 --- a/src/Stores/CrestApps.Core.Data.YesSql/ServiceCollectionExtensions.cs +++ b/src/Stores/CrestApps.Core.Data.YesSql/ServiceCollectionExtensions.cs @@ -9,6 +9,7 @@ using CrestApps.Core.AI.Memory; using CrestApps.Core.AI.Models; using CrestApps.Core.AI.Profiles; +using CrestApps.Core.AI.Security; using CrestApps.Core.Builders; using CrestApps.Core.Data.YesSql.Indexes; using CrestApps.Core.Data.YesSql.Indexes.A2A; @@ -379,6 +380,7 @@ public static IServiceCollection AddCoreAIChatSessionBaseStoresYesSql(this IServ { ArgumentNullException.ThrowIfNull(services); + services.TryAddSingleton(); services.AddScoped(); services.AddScoped(); services.AddScoped(); diff --git a/src/Stores/CrestApps.Core.Data.YesSql/Services/YesSqlAIChatSessionManager.cs b/src/Stores/CrestApps.Core.Data.YesSql/Services/YesSqlAIChatSessionManager.cs index 583d6e8f..a6efc6e1 100644 --- a/src/Stores/CrestApps.Core.Data.YesSql/Services/YesSqlAIChatSessionManager.cs +++ b/src/Stores/CrestApps.Core.Data.YesSql/Services/YesSqlAIChatSessionManager.cs @@ -4,9 +4,9 @@ using CrestApps.Core.AI.Documents; using CrestApps.Core.AI.Models; using CrestApps.Core.AI.ResponseHandling; +using CrestApps.Core.AI.Security; using CrestApps.Core.Data.YesSql.Indexes.AIChat; using Microsoft.AspNetCore.Http; -using Microsoft.Extensions.AI; using Microsoft.Extensions.Options; using YesSql; using ISession = YesSql.ISession; @@ -16,6 +16,7 @@ namespace CrestApps.Core.Data.YesSql.Services; public sealed class YesSqlAIChatSessionManager : IAIChatSessionManager { private readonly IHttpContextAccessor _httpContextAccessor; + private readonly IAIVisitorIdentityResolver _visitorIdentityResolver; private readonly ISession _session; private readonly IAIChatSessionPromptStore _promptStore; private readonly IEnumerable _documentCleanupServices; @@ -33,6 +34,7 @@ public sealed class YesSqlAIChatSessionManager : IAIChatSessionManager /// The options. public YesSqlAIChatSessionManager( IHttpContextAccessor httpContextAccessor, + IAIVisitorIdentityResolver visitorIdentityResolver, ISession session, IAIChatSessionPromptStore promptStore, IEnumerable documentCleanupServices, @@ -40,6 +42,7 @@ public YesSqlAIChatSessionManager( IOptions options) { _httpContextAccessor = httpContextAccessor; + _visitorIdentityResolver = visitorIdentityResolver; _session = session; _promptStore = promptStore; _documentCleanupServices = documentCleanupServices; @@ -132,27 +135,21 @@ public async Task NewAsync(AIProfile profile, NewAIChatSessionCon var user = _httpContextAccessor.HttpContext?.User; var userId = user?.FindFirstValue(ClaimTypes.NameIdentifier) ?? user?.Identity?.Name; + var visitorIdentity = _visitorIdentityResolver.Resolve(); + session.RemoteAddress = visitorIdentity.RemoteAddress; + session.RemoteAddressHash = visitorIdentity.RemoteAddressHash; if (!string.IsNullOrEmpty(userId)) { session.UserId = userId; } + else + { + session.ClientId = visitorIdentity.VisitorId; + } if (profile.Type == AIProfileType.Chat) { - if (profile.TryGet(out var profileMetadata) && !string.IsNullOrWhiteSpace(profileMetadata.InitialPrompt)) - { - await _promptStore.CreateAsync(new AIChatSessionPrompt - { - ItemId = UniqueId.GenerateId(), - SessionId = session.SessionId, - Role = ChatRole.Assistant, - Title = profile.PromptSubject, - Content = profileMetadata.InitialPrompt, - CreatedUtc = now, - }, cancellationToken); - } - var handlerSettings = profile.GetOrCreateSettings(); if (!string.IsNullOrEmpty(handlerSettings.InitialResponseHandlerName)) diff --git a/tests/CrestApps.Core.Tests/Framework/AI/Security/DefaultAIVisitorIdentityResolverTests.cs b/tests/CrestApps.Core.Tests/Framework/AI/Security/DefaultAIVisitorIdentityResolverTests.cs new file mode 100644 index 00000000..b3b28151 --- /dev/null +++ b/tests/CrestApps.Core.Tests/Framework/AI/Security/DefaultAIVisitorIdentityResolverTests.cs @@ -0,0 +1,87 @@ +using CrestApps.Core.AI.Chat.Security; +using CrestApps.Core.AI.Security; +using Microsoft.AspNetCore.DataProtection; +using Microsoft.AspNetCore.Http; +using Microsoft.Extensions.Hosting; +using Microsoft.Extensions.Options; + +namespace CrestApps.Core.Tests.Framework.AI.Security; + +public sealed class DefaultAIVisitorIdentityResolverTests +{ + [Fact] + public void Resolve_WhenHashedModeEnabled_ReturnsHashOnly() + { + var resolver = CreateResolver(AIVisitorRemoteAddressMode.Hashed, "203.0.113.5"); + + var identity = resolver.Resolve(); + + Assert.NotNull(identity.VisitorId); + Assert.Null(identity.RemoteAddress); + Assert.False(string.IsNullOrWhiteSpace(identity.RemoteAddressHash)); + } + + [Fact] + public void Resolve_WhenPlainTextModeEnabled_ReturnsPlainTextAddressOnly() + { + var resolver = CreateResolver(AIVisitorRemoteAddressMode.PlainText, "198.51.100.7"); + + var identity = resolver.Resolve(); + + Assert.Equal("198.51.100.7", identity.RemoteAddress); + Assert.Null(identity.RemoteAddressHash); + } + + [Fact] + public void Resolve_WhenRemoteAddressCaptureDisabled_ReturnsNoAddressData() + { + var resolver = CreateResolver(AIVisitorRemoteAddressMode.Disabled, "192.0.2.20"); + + var identity = resolver.Resolve(); + + Assert.Null(identity.RemoteAddress); + Assert.Null(identity.RemoteAddressHash); + } + + [Fact] + public void Resolve_WhenEncryptedModeEnabled_ReturnsEncryptedAddressAndHash() + { + var resolver = CreateResolver(AIVisitorRemoteAddressMode.Encrypted, "192.0.2.21"); + + var identity = resolver.Resolve(); + + Assert.NotNull(identity.RemoteAddress); + Assert.NotEqual("192.0.2.21", identity.RemoteAddress); + Assert.False(string.IsNullOrWhiteSpace(identity.RemoteAddressHash)); + } + + private static DefaultAIVisitorIdentityResolver CreateResolver(AIVisitorRemoteAddressMode mode, string remoteAddress) + { + var httpContext = new DefaultHttpContext(); + httpContext.Connection.RemoteIpAddress = System.Net.IPAddress.Parse(remoteAddress); + + return new DefaultAIVisitorIdentityResolver( + new HttpContextAccessor + { + HttpContext = httpContext, + }, + Options.Create(new AIVisitorIdentityOptions + { + RemoteAddressMode = mode, + RemoteAddressHashSalt = "test-salt", + }), + new TestHostEnvironment(), + new EphemeralDataProtectionProvider()); + } + + private sealed class TestHostEnvironment : IHostEnvironment + { + public string EnvironmentName { get; set; } = "Development"; + + public string ApplicationName { get; set; } = "CrestApps.Tests"; + + public string ContentRootPath { get; set; } = AppContext.BaseDirectory; + + public Microsoft.Extensions.FileProviders.IFileProvider ContentRootFileProvider { get; set; } + } +} diff --git a/tests/CrestApps.Core.Tests/Framework/AI/Security/DefaultChatRateLimiterTests.cs b/tests/CrestApps.Core.Tests/Framework/AI/Security/DefaultChatRateLimiterTests.cs index 4672cd0b..a7fd1926 100644 --- a/tests/CrestApps.Core.Tests/Framework/AI/Security/DefaultChatRateLimiterTests.cs +++ b/tests/CrestApps.Core.Tests/Framework/AI/Security/DefaultChatRateLimiterTests.cs @@ -79,7 +79,12 @@ public async Task EvaluateAsync_AfterWindowExpires_AllowsAgain() [Fact] public async Task EvaluateAsync_DifferentSessions_TrackedIndependently() { - var limiter = CreateLimiter(maxMessages: 2); + var limiter = CreateLimiter( + maxMessages: 2, + rateLimitingOptions: new AIChatRateLimitingOptions + { + AnonymousMessagePartitions = ChatRateLimitPartition.Session, + }); var context1 = CreateContext(sessionId: "session-1"); var context2 = CreateContext(sessionId: "session-2"); @@ -113,6 +118,56 @@ public async Task EvaluateAsync_KeysByUserIdentity_WhenAvailable() Assert.True(result.IsThrottled); } + [Fact] + public async Task EvaluateAsync_KeysAnonymousTrafficByVisitorIdAcrossSessions() + { + var limiter = CreateLimiter(maxMessages: 2); + var context1 = CreateContext(sessionId: "session-A", visitorId: "visitor-1"); + var context2 = CreateContext(sessionId: "session-B", visitorId: "visitor-1"); + + await limiter.EvaluateAsync(context1, TestContext.Current.CancellationToken); + await limiter.EvaluateAsync(context2, TestContext.Current.CancellationToken); + + var result = await limiter.EvaluateAsync(context1, TestContext.Current.CancellationToken); + + Assert.True(result.IsThrottled); + } + + [Fact] + public async Task EvaluateAsync_UsesRemoteAddressHashFallbackWhenVisitorIdChanges() + { + var limiter = CreateLimiter(maxMessages: 2); + var context1 = CreateContext(sessionId: "session-A", visitorId: "visitor-1", remoteAddressHash: "ip-1"); + var context2 = CreateContext(sessionId: "session-B", visitorId: "visitor-2", remoteAddressHash: "ip-1"); + + await limiter.EvaluateAsync(context1, TestContext.Current.CancellationToken); + await limiter.EvaluateAsync(context2, TestContext.Current.CancellationToken); + + var result = await limiter.EvaluateAsync(context1, TestContext.Current.CancellationToken); + + Assert.True(result.IsThrottled); + } + + [Fact] + public async Task EvaluateAsync_UsesPlainTextRemoteAddressWhenConfigured() + { + var limiter = CreateLimiter( + maxMessages: 2, + rateLimitingOptions: new AIChatRateLimitingOptions + { + AnonymousMessagePartitions = ChatRateLimitPartition.NetworkAddress, + }); + var context1 = CreateContext(sessionId: "session-A", visitorId: "visitor-1", remoteAddress: "203.0.113.10"); + var context2 = CreateContext(sessionId: "session-B", visitorId: "visitor-2", remoteAddress: "203.0.113.10"); + + await limiter.EvaluateAsync(context1, TestContext.Current.CancellationToken); + await limiter.EvaluateAsync(context2, TestContext.Current.CancellationToken); + + var result = await limiter.EvaluateAsync(context1, TestContext.Current.CancellationToken); + + Assert.True(result.IsThrottled); + } + [Fact] public async Task EvaluateAsync_ProfileOverridesRateLimit() { @@ -156,7 +211,12 @@ public async Task EvaluateAsync_ProfileDisablesRateLimit() [Fact] public async Task Reset_ClearsSessionTracking() { - var limiter = CreateLimiter(maxMessages: 2); + var limiter = CreateLimiter( + maxMessages: 2, + rateLimitingOptions: new AIChatRateLimitingOptions + { + AnonymousMessagePartitions = ChatRateLimitPartition.Session, + }); var context = CreateContext(sessionId: "session-to-reset"); await limiter.EvaluateAsync(context, TestContext.Current.CancellationToken); @@ -204,6 +264,7 @@ public async Task EvaluateAsync_SlidingWindow_EvictsOldEntries() private static DefaultChatRateLimiter CreateLimiter( int maxMessages, int windowSeconds = 60, + AIChatRateLimitingOptions rateLimitingOptions = null, TimeProvider timeProvider = null) { var options = Options.Create(new PromptSecurityOptions @@ -214,13 +275,17 @@ private static DefaultChatRateLimiter CreateLimiter( return new DefaultChatRateLimiter( timeProvider ?? TimeProvider.System, + Options.Create(rateLimitingOptions ?? new AIChatRateLimitingOptions()), options, NullLogger.Instance); } private static PromptSecurityContext CreateContext( string sessionId = "test-session", - System.Security.Claims.ClaimsPrincipal user = null) + System.Security.Claims.ClaimsPrincipal user = null, + string visitorId = null, + string remoteAddressHash = null, + string remoteAddress = null) { return new PromptSecurityContext { @@ -229,6 +294,9 @@ private static PromptSecurityContext CreateContext( ProfileId = "profile-1", User = user, ConnectionId = "conn-1", + VisitorId = visitorId, + RemoteAddressHash = remoteAddressHash, + RemoteAddress = remoteAddress, }; } diff --git a/tests/CrestApps.Core.Tests/Framework/AI/Security/DefaultChatSessionStartRateLimiterTests.cs b/tests/CrestApps.Core.Tests/Framework/AI/Security/DefaultChatSessionStartRateLimiterTests.cs new file mode 100644 index 00000000..bfb760a5 --- /dev/null +++ b/tests/CrestApps.Core.Tests/Framework/AI/Security/DefaultChatSessionStartRateLimiterTests.cs @@ -0,0 +1,91 @@ +using CrestApps.Core.AI.Security; +using Microsoft.Extensions.Logging.Abstractions; +using Microsoft.Extensions.Options; + +namespace CrestApps.Core.Tests.Framework.AI.Security; + +public sealed class DefaultChatSessionStartRateLimiterTests +{ + [Fact] + public async Task EvaluateAsync_WhenDisabled_ReturnsAllowed() + { + var limiter = CreateLimiter(maxSessions: 0); + var result = await limiter.EvaluateAsync(CreateContext(), TestContext.Current.CancellationToken); + + Assert.False(result.IsThrottled); + } + + [Fact] + public async Task EvaluateAsync_AnonymousVisitorAcrossRequests_IsThrottled() + { + var limiter = CreateLimiter(maxSessions: 2); + var context = CreateContext(); + + await limiter.EvaluateAsync(context, TestContext.Current.CancellationToken); + await limiter.EvaluateAsync(context, TestContext.Current.CancellationToken); + + var result = await limiter.EvaluateAsync(context, TestContext.Current.CancellationToken); + + Assert.True(result.IsThrottled); + } + + [Fact] + public async Task EvaluateAsync_AuthenticatedUser_IsIgnored() + { + var limiter = CreateLimiter(maxSessions: 1); + var context = CreateContext(user: TestHelpers.CreateClaimsPrincipal("user-1")); + + await limiter.EvaluateAsync(context, TestContext.Current.CancellationToken); + var result = await limiter.EvaluateAsync(context, TestContext.Current.CancellationToken); + + Assert.False(result.IsThrottled); + } + + [Fact] + public async Task EvaluateAsync_UsesPlainTextRemoteAddressWhenConfigured() + { + var limiter = CreateLimiter( + maxSessions: 2, + rateLimitingOptions: new AIChatRateLimitingOptions + { + AnonymousSessionStartPartitions = ChatRateLimitPartition.NetworkAddress, + }); + var context = CreateContext(remoteAddress: "198.51.100.25", remoteAddressHash: null); + + await limiter.EvaluateAsync(context, TestContext.Current.CancellationToken); + await limiter.EvaluateAsync(context, TestContext.Current.CancellationToken); + + var result = await limiter.EvaluateAsync(context, TestContext.Current.CancellationToken); + + Assert.True(result.IsThrottled); + } + + private static DefaultChatSessionStartRateLimiter CreateLimiter( + int maxSessions, + AIChatRateLimitingOptions rateLimitingOptions = null) + { + return new DefaultChatSessionStartRateLimiter( + TimeProvider.System, + Options.Create(rateLimitingOptions ?? new AIChatRateLimitingOptions()), + Options.Create(new PromptSecurityOptions + { + MaxAnonymousSessionsPerWindow = maxSessions, + AnonymousSessionRateLimitWindow = TimeSpan.FromMinutes(10), + }), + NullLogger.Instance); + } + + private static PromptSecurityContext CreateContext( + System.Security.Claims.ClaimsPrincipal user = null, + string remoteAddressHash = "ip-1", + string remoteAddress = null) + { + return new PromptSecurityContext + { + User = user, + VisitorId = "visitor-1", + RemoteAddressHash = remoteAddressHash, + RemoteAddress = remoteAddress, + }; + } +} diff --git a/tests/CrestApps.Core.Tests/Framework/AI/Security/DefaultPromptSecurityServiceTests.cs b/tests/CrestApps.Core.Tests/Framework/AI/Security/DefaultPromptSecurityServiceTests.cs index 22b7a279..264692b2 100644 --- a/tests/CrestApps.Core.Tests/Framework/AI/Security/DefaultPromptSecurityServiceTests.cs +++ b/tests/CrestApps.Core.Tests/Framework/AI/Security/DefaultPromptSecurityServiceTests.cs @@ -245,6 +245,7 @@ private static DefaultPromptSecurityService CreateService( rateLimiter ??= new DefaultChatRateLimiter( TimeProvider.System, + Options.Create(new AIChatRateLimitingOptions()), configuredOptions, NullLogger.Instance); diff --git a/tests/CrestApps.Core.Tests/Framework/Mvc/AIChatHubCoreTests.cs b/tests/CrestApps.Core.Tests/Framework/Mvc/AIChatHubCoreTests.cs index a521dcbf..7b645c9d 100644 --- a/tests/CrestApps.Core.Tests/Framework/Mvc/AIChatHubCoreTests.cs +++ b/tests/CrestApps.Core.Tests/Framework/Mvc/AIChatHubCoreTests.cs @@ -1,3 +1,4 @@ +using CrestApps.Core.AI; using CrestApps.Core.AI.Chat; using CrestApps.Core.AI.Chat.Hubs; using CrestApps.Core.AI.Exceptions; @@ -5,6 +6,7 @@ using CrestApps.Core.Services; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging.Abstractions; +using Moq; namespace CrestApps.Core.Tests.Framework.Mvc; @@ -65,6 +67,66 @@ public void GetFriendlyErrorMessage_WithInvalidChatModelSettings_ReturnsProfileG Assert.Equal("The chat model settings are missing or invalid. Update the Chat model in the AI Profile or the global AI settings.", message); } + [Fact] + public async Task EnsureInitialPromptAsync_PersistsInitialPromptOnlyWhenSessionHasNoMessages() + { + var promptStore = new Mock(); + promptStore.Setup(store => store.CountAsync("session-1")).ReturnsAsync(0); + promptStore + .Setup(store => store.CreateAsync(It.IsAny(), It.IsAny())) + .Returns(ValueTask.CompletedTask); + var profile = new AIProfile + { + ItemId = "profile-1", + Type = AIProfileType.Chat, + PromptSubject = "Welcome", + }; + profile.Put(new AIProfileMetadata + { + InitialPrompt = "Hello there", + }); + var chatSession = new AIChatSession + { + SessionId = "session-1", + CreatedUtc = new DateTime(2026, 07, 15, 18, 0, 0, DateTimeKind.Utc), + }; + var hub = new TestAIChatHub(new ServiceCollection().BuildServiceProvider()); + + await hub.EnsureInitialPromptForTestAsync(promptStore.Object, profile, chatSession, TestContext.Current.CancellationToken); + + promptStore.Verify(store => store.CreateAsync(It.Is(prompt => + prompt.SessionId == "session-1" && + prompt.Role.Value == "assistant" && + prompt.Title == "Welcome" && + prompt.Content == "Hello there" && + prompt.CreatedUtc == chatSession.CreatedUtc), It.IsAny()), Times.Once); + } + + [Fact] + public async Task EnsureInitialPromptAsync_DoesNothingWhenSessionAlreadyHasMessages() + { + var promptStore = new Mock(MockBehavior.Strict); + promptStore.Setup(store => store.CountAsync("session-1")).ReturnsAsync(1); + var profile = new AIProfile + { + ItemId = "profile-1", + Type = AIProfileType.Chat, + }; + profile.Put(new AIProfileMetadata + { + InitialPrompt = "Hello there", + }); + var hub = new TestAIChatHub(new ServiceCollection().BuildServiceProvider()); + + await hub.EnsureInitialPromptForTestAsync(promptStore.Object, profile, new AIChatSession + { + SessionId = "session-1", + CreatedUtc = DateTime.UtcNow, + }, TestContext.Current.CancellationToken); + + promptStore.Verify(store => store.CountAsync("session-1"), Times.Once); + } + private sealed class TestAIChatHub : AIChatHubCore { public TestAIChatHub(IServiceProvider services) @@ -82,6 +144,15 @@ public string GetFriendlyErrorMessageForTest(Exception ex) return GetFriendlyErrorMessage(ex); } + public Task EnsureInitialPromptForTestAsync( + IAIChatSessionPromptStore promptStore, + AIProfile profile, + AIChatSession chatSession, + CancellationToken cancellationToken = default) + { + return EnsureInitialPromptAsync(promptStore, profile, chatSession, cancellationToken); + } + public static bool IsEndedStatusForTest(ChatSessionStatus status) { var method = typeof(AIChatHubCore).GetMethod( diff --git a/tests/CrestApps.Core.Tests/Framework/Mvc/YesSqlAIChatSessionManagerTests.cs b/tests/CrestApps.Core.Tests/Framework/Mvc/YesSqlAIChatSessionManagerTests.cs index 6f46bddd..b8a611e0 100644 --- a/tests/CrestApps.Core.Tests/Framework/Mvc/YesSqlAIChatSessionManagerTests.cs +++ b/tests/CrestApps.Core.Tests/Framework/Mvc/YesSqlAIChatSessionManagerTests.cs @@ -3,11 +3,11 @@ using CrestApps.Core.AI; using CrestApps.Core.AI.Models; using CrestApps.Core.AI.ResponseHandling; +using CrestApps.Core.AI.Security; using CrestApps.Core.Data.YesSql; using CrestApps.Core.Data.YesSql.Indexes.AIChat; using CrestApps.Core.Data.YesSql.Services; using Microsoft.AspNetCore.Http; -using Microsoft.Extensions.AI; using Microsoft.Extensions.Options; using Moq; @@ -16,7 +16,7 @@ namespace CrestApps.Core.Tests.Framework.Mvc; public sealed class YesSqlAIChatSessionManagerTests { [Fact] - public async Task NewAsync_WithInitialPrompt_ShouldCreateAssistantPromptThatParticipatesInHistory() + public async Task NewAsync_WithInitialPrompt_DoesNotPersistAssistantPromptUntilUserMessageArrives() { var promptStore = new Mock(); var httpContextAccessor = new Mock(); @@ -45,6 +45,7 @@ public async Task NewAsync_WithInitialPrompt_ShouldCreateAssistantPromptThatPart var manager = new YesSqlAIChatSessionManager( httpContextAccessor.Object, + CreateVisitorResolver().Object, new Mock().Object, promptStore.Object, [], @@ -55,14 +56,7 @@ public async Task NewAsync_WithInitialPrompt_ShouldCreateAssistantPromptThatPart Assert.Equal("user-1", session.UserId); Assert.Equal("handoff", session.ResponseHandlerName); - promptStore.Verify(store => store.CreateAsync(It.Is(prompt => - prompt.SessionId == session.SessionId && - prompt.Role == ChatRole.Assistant && - prompt.Title == "Welcome" && - prompt.Content == "Hello there" && - !prompt.IsGeneratedPrompt && - prompt.CreatedUtc != default), It.IsAny()), - Times.Once); + promptStore.VerifyNoOtherCalls(); } [Fact] @@ -81,6 +75,7 @@ public async Task NewAsync_WhenIdentityHasNoNameIdentifier_UsesIdentityName() var manager = new YesSqlAIChatSessionManager( httpContextAccessor.Object, + CreateVisitorResolver().Object, new Mock(MockBehavior.Strict).Object, promptStore.Object, [], @@ -98,6 +93,33 @@ public async Task NewAsync_WhenIdentityHasNoNameIdentifier_UsesIdentityName() promptStore.VerifyNoOtherCalls(); } + [Fact] + public async Task NewAsync_WhenAnonymous_AssignsStableClientIdFromVisitorResolver() + { + var promptStore = new Mock(MockBehavior.Strict); + var httpContextAccessor = new Mock(); + httpContextAccessor.Setup(accessor => accessor.HttpContext).Returns(new DefaultHttpContext()); + var visitorResolver = CreateVisitorResolver("visitor-42"); + var manager = new YesSqlAIChatSessionManager( + httpContextAccessor.Object, + visitorResolver.Object, + new Mock(MockBehavior.Strict).Object, + promptStore.Object, + [], + TimeProvider.System, + Options.Create(new YesSqlStoreOptions())); + + var session = await manager.NewAsync(new AIProfile + { + ItemId = "profile-1", + Type = AIProfileType.Chat, + }, new NewAIChatSessionContext(), TestContext.Current.CancellationToken); + + Assert.Equal("visitor-42", session.ClientId); + Assert.Null(session.UserId); + visitorResolver.Verify(resolver => resolver.Resolve(), Times.Once); + } + [Fact] public async Task NewAsync_WhenProfileIsNotChat_DoesNotCreatePromptOrAssignInitialHandler() { @@ -120,6 +142,7 @@ public async Task NewAsync_WhenProfileIsNotChat_DoesNotCreatePromptOrAssignIniti var manager = new YesSqlAIChatSessionManager( Mock.Of(accessor => accessor.HttpContext == null), + CreateVisitorResolver().Object, new Mock(MockBehavior.Strict).Object, promptStore.Object, [], @@ -154,6 +177,7 @@ public async Task NewAsync_WhenInitialPromptIsBlank_DoesNotCreateAssistantPrompt var manager = new YesSqlAIChatSessionManager( Mock.Of(accessor => accessor.HttpContext == null), + CreateVisitorResolver().Object, new Mock(MockBehavior.Strict).Object, promptStore.Object, [], @@ -195,6 +219,7 @@ public async Task SaveAsync_UpdatesLastActivityAndPersistsSession() var sessionManager = new YesSqlAIChatSessionManager( new Mock(MockBehavior.Strict).Object, + CreateVisitorResolver().Object, sessionStore.Object, new Mock(MockBehavior.Strict).Object, [], @@ -218,6 +243,7 @@ public async Task SaveAsync_WhenSessionIsNull_ThrowsArgumentNullException() { var sessionManager = new YesSqlAIChatSessionManager( new Mock(MockBehavior.Strict).Object, + CreateVisitorResolver().Object, new Mock(MockBehavior.Strict).Object, new Mock(MockBehavior.Strict).Object, [], @@ -232,6 +258,7 @@ public async Task FindByIdAsync_WhenIdIsEmpty_ThrowsArgumentException() { var sessionManager = new YesSqlAIChatSessionManager( new Mock(MockBehavior.Strict).Object, + CreateVisitorResolver().Object, new Mock(MockBehavior.Strict).Object, new Mock(MockBehavior.Strict).Object, [], @@ -246,6 +273,7 @@ public async Task DeleteAsync_WhenSessionIdIsEmpty_ThrowsArgumentException() { var sessionManager = new YesSqlAIChatSessionManager( new Mock(MockBehavior.Strict).Object, + CreateVisitorResolver().Object, new Mock(MockBehavior.Strict).Object, new Mock(MockBehavior.Strict).Object, [], @@ -254,4 +282,15 @@ public async Task DeleteAsync_WhenSessionIdIsEmpty_ThrowsArgumentException() await Assert.ThrowsAnyAsync(() => sessionManager.DeleteAsync(string.Empty, TestContext.Current.CancellationToken)); } + + private static Mock CreateVisitorResolver(string visitorId = "visitor-default") + { + var visitorResolver = new Mock(); + visitorResolver.Setup(resolver => resolver.Resolve()).Returns(new AIVisitorIdentity + { + VisitorId = visitorId, + }); + + return visitorResolver; + } } diff --git a/tests/CrestApps.Core.Tests/Framework/Startup/AIChatWidgetAccessEvaluatorTests.cs b/tests/CrestApps.Core.Tests/Framework/Startup/AIChatWidgetAccessEvaluatorTests.cs new file mode 100644 index 00000000..06a85617 --- /dev/null +++ b/tests/CrestApps.Core.Tests/Framework/Startup/AIChatWidgetAccessEvaluatorTests.cs @@ -0,0 +1,40 @@ +using System.Security.Claims; +using CrestApps.Core.Startup.Shared.Services; + +namespace CrestApps.Core.Tests.Framework.Startup; + +public sealed class AIChatWidgetAccessEvaluatorTests +{ + [Fact] + public void CanAccessProfile_AllowsAuthenticatedUsers() + { + var user = new ClaimsPrincipal(new ClaimsIdentity( + [ + new Claim(ClaimTypes.Name, "admin"), + ], "Cookies")); + + var result = AIChatWidgetAccessEvaluator.CanAccessProfile(user, "widget-profile", "other-profile"); + + Assert.True(result); + } + + [Fact] + public void CanAccessProfile_AllowsAnonymousUsersForConfiguredWidgetProfile() + { + var user = new ClaimsPrincipal(new ClaimsIdentity()); + + var result = AIChatWidgetAccessEvaluator.CanAccessProfile(user, "widget-profile", "widget-profile"); + + Assert.True(result); + } + + [Fact] + public void CanAccessProfile_BlocksAnonymousUsersForOtherProfiles() + { + var user = new ClaimsPrincipal(new ClaimsIdentity()); + + var result = AIChatWidgetAccessEvaluator.CanAccessProfile(user, "widget-profile", "other-profile"); + + Assert.False(result); + } +}