@optifye/dashboard-core 6.2.0 → 6.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -21,9 +21,9 @@ import jsPDF, { jsPDF as jsPDF$1 } from 'jspdf';
21
21
  import * as SelectPrimitive from '@radix-ui/react-select';
22
22
  import videojs from 'video.js';
23
23
  import 'video.js/dist/video-js.css';
24
- import { Readable } from 'stream';
25
24
  import { toast } from 'sonner';
26
25
  import { getSignedUrl } from '@aws-sdk/s3-request-presigner';
26
+ import { Readable } from 'stream';
27
27
 
28
28
  var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
29
29
  get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
@@ -7263,7 +7263,7 @@ var S3ClipsService = class {
7263
7263
  "best_cycle_time",
7264
7264
  "worst_cycle_time",
7265
7265
  "long_cycle_time",
7266
- "cycle_completions",
7266
+ "cycle_completion",
7267
7267
  "bottleneck"
7268
7268
  ];
7269
7269
  console.log(`[S3ClipsService] ${buildIndex ? "Building video index and counting" : "Fast counting"} clips for ${workspaceId} on ${date}, shift ${shiftId}`);
@@ -29463,386 +29463,6 @@ var FactoryView = ({
29463
29463
  };
29464
29464
  var AuthenticatedFactoryView = withAuth(FactoryView);
29465
29465
  var FactoryView_default = FactoryView;
29466
-
29467
- // src/lib/api/optifye-agent.ts
29468
- var OPTIFYE_API_URL = "https://optifye-agent-production.up.railway.app";
29469
- var OptifyeAgentClient = class {
29470
- constructor(apiUrl = OPTIFYE_API_URL) {
29471
- this.apiUrl = apiUrl;
29472
- }
29473
- /**
29474
- * Call Optifye Agent for manufacturing analysis
29475
- */
29476
- async getManufacturingInsights(userQuestion, lineId, shiftId, companyId, context) {
29477
- try {
29478
- const requestData = {
29479
- prompt: userQuestion,
29480
- line_id: lineId,
29481
- shift_id: shiftId,
29482
- company_id: companyId
29483
- };
29484
- if (context) {
29485
- requestData.context = context;
29486
- }
29487
- console.log("[OptifyeAgent] Sending request:", requestData);
29488
- const response = await fetch(`${this.apiUrl}/api/custom-analysis`, {
29489
- method: "POST",
29490
- headers: {
29491
- "Content-Type": "application/json"
29492
- },
29493
- body: JSON.stringify(requestData),
29494
- signal: AbortSignal.timeout(6e4)
29495
- // 60 second timeout
29496
- });
29497
- const responseText = await response.text();
29498
- console.log("[OptifyeAgent] Response status:", response.status);
29499
- console.log("[OptifyeAgent] Response text:", responseText);
29500
- let result;
29501
- try {
29502
- result = JSON.parse(responseText);
29503
- } catch (parseError) {
29504
- console.error("[OptifyeAgent] Failed to parse response as JSON:", parseError);
29505
- if (responseText.includes("'Agent' object has no attribute")) {
29506
- return {
29507
- success: false,
29508
- error: "Server error: The AI agent service is experiencing issues. Please try again later or contact support."
29509
- };
29510
- }
29511
- return {
29512
- success: false,
29513
- error: `Invalid response format from server: ${responseText.substring(0, 200)}`
29514
- };
29515
- }
29516
- if (response.ok) {
29517
- return {
29518
- success: result.success ?? true,
29519
- analysis: result.analysis || result.response || result.message || result.data,
29520
- timestamp: result.timestamp,
29521
- error: result.error
29522
- };
29523
- } else {
29524
- const errorMsg = result.error || result.message || `API request failed: ${response.status}`;
29525
- console.error("[OptifyeAgent] API error:", errorMsg);
29526
- if (errorMsg.includes("'Agent' object has no attribute")) {
29527
- return {
29528
- success: false,
29529
- error: "The AI service is currently being updated. Please try again in a few moments."
29530
- };
29531
- }
29532
- return {
29533
- success: false,
29534
- error: errorMsg
29535
- };
29536
- }
29537
- } catch (error) {
29538
- const errorMsg = error instanceof Error ? `Failed to connect to Optifye Agent: ${error.message}` : "Failed to connect to Optifye Agent";
29539
- console.error("[OptifyeAgent] Request failed:", error);
29540
- if (error instanceof Error && error.name === "AbortError") {
29541
- return {
29542
- success: false,
29543
- error: "Request timed out. The AI agent is taking too long to respond. Please try again."
29544
- };
29545
- }
29546
- return {
29547
- success: false,
29548
- error: errorMsg
29549
- };
29550
- }
29551
- }
29552
- /**
29553
- * Check if Optifye Agent API is healthy
29554
- */
29555
- async checkHealth() {
29556
- try {
29557
- const response = await fetch(`${this.apiUrl}/health`, {
29558
- signal: AbortSignal.timeout(1e4)
29559
- // 10 second timeout
29560
- });
29561
- if (response.ok) {
29562
- const healthData = await response.json();
29563
- return healthData.status === "healthy";
29564
- }
29565
- return false;
29566
- } catch (error) {
29567
- console.error("[OptifyeAgent] Health check failed:", error);
29568
- return false;
29569
- }
29570
- }
29571
- };
29572
- var optifyeAgentClient = new OptifyeAgentClient();
29573
- async function getManufacturingInsights(userQuestion, lineId, shiftId, companyId, context) {
29574
- if (!userQuestion || !userQuestion.trim()) {
29575
- return {
29576
- success: false,
29577
- error: "Please provide a question"
29578
- };
29579
- }
29580
- if (!lineId || !companyId) {
29581
- console.warn("[OptifyeAgent] Missing required IDs:", { lineId, companyId });
29582
- }
29583
- return optifyeAgentClient.getManufacturingInsights(
29584
- userQuestion,
29585
- lineId,
29586
- shiftId,
29587
- companyId,
29588
- context
29589
- );
29590
- }
29591
- function createStreamProxyHandler(config) {
29592
- const cloudFrontDomain = config?.cloudFrontDomain || "https://d1eiob0chi5jw.cloudfront.net";
29593
- return async function handler(req, res) {
29594
- if (req.method !== "GET") {
29595
- return res.status(405).json({ error: "Method not allowed" });
29596
- }
29597
- const { path } = req.query;
29598
- if (!path || !Array.isArray(path)) {
29599
- return res.status(400).json({ error: "Missing path parameter" });
29600
- }
29601
- const fullPath = path.join("/");
29602
- const targetUrl = `${cloudFrontDomain}/${fullPath}`;
29603
- try {
29604
- console.log(`[HLS Stream Proxy] Streaming: ${targetUrl}`);
29605
- const response = await fetch(targetUrl, {
29606
- method: "GET",
29607
- headers: {
29608
- "User-Agent": "NextJS-HLS-Stream-Proxy",
29609
- // Pass through range headers for partial content requests
29610
- ...req.headers.range && { "Range": req.headers.range }
29611
- }
29612
- });
29613
- if (!response.ok) {
29614
- console.error(`[HLS Stream Proxy] CloudFront error: ${response.status} ${response.statusText}`);
29615
- return res.status(response.status).json({
29616
- error: `CloudFront request failed: ${response.statusText}`
29617
- });
29618
- }
29619
- const contentType = response.headers.get("content-type") || "application/octet-stream";
29620
- const contentLength = response.headers.get("content-length");
29621
- res.setHeader("Access-Control-Allow-Origin", "*");
29622
- res.setHeader("Access-Control-Allow-Methods", "GET, HEAD");
29623
- res.setHeader("Access-Control-Allow-Headers", "Content-Type, Range");
29624
- res.setHeader("Access-Control-Expose-Headers", "Content-Length, Content-Range");
29625
- res.setHeader("Content-Type", contentType);
29626
- if (contentLength) {
29627
- res.setHeader("Content-Length", contentLength);
29628
- }
29629
- if (fullPath.endsWith(".m3u8")) {
29630
- res.setHeader("Content-Type", "application/vnd.apple.mpegurl");
29631
- } else if (fullPath.endsWith(".ts")) {
29632
- res.setHeader("Content-Type", "video/mp2t");
29633
- }
29634
- if (response.status === 206) {
29635
- res.status(206);
29636
- const contentRange = response.headers.get("content-range");
29637
- if (contentRange) {
29638
- res.setHeader("Content-Range", contentRange);
29639
- }
29640
- res.setHeader("Accept-Ranges", "bytes");
29641
- }
29642
- if (response.body) {
29643
- const reader = response.body.getReader();
29644
- const nodeStream = new Readable({
29645
- async read() {
29646
- try {
29647
- const { done, value } = await reader.read();
29648
- if (done) {
29649
- this.push(null);
29650
- } else {
29651
- this.push(Buffer.from(value));
29652
- }
29653
- } catch (error) {
29654
- console.error("[HLS Stream Proxy] Stream read error:", error);
29655
- this.destroy(error);
29656
- }
29657
- }
29658
- });
29659
- nodeStream.pipe(res);
29660
- req.on("close", () => {
29661
- reader.cancel();
29662
- nodeStream.destroy();
29663
- });
29664
- } else {
29665
- const buffer = await response.arrayBuffer();
29666
- res.send(Buffer.from(buffer));
29667
- }
29668
- } catch (error) {
29669
- console.error("[HLS Stream Proxy] Error:", error);
29670
- res.status(500).json({
29671
- error: "Failed to stream from CloudFront",
29672
- details: error instanceof Error ? error.message : String(error)
29673
- });
29674
- }
29675
- };
29676
- }
29677
- var streamProxyConfig = {
29678
- api: {
29679
- bodyParser: false,
29680
- responseLimit: false
29681
- }
29682
- };
29683
-
29684
- // src/lib/api/slackApi.ts
29685
- var SlackAPI = class {
29686
- /**
29687
- * Sends a support ticket notification to Slack.
29688
- * 1. If slackWebhookUrl is configured, send directly (preferred)
29689
- * 2. Otherwise, if slackProxyEndpoint is configured, send to the proxy
29690
- * If neither is configured, logs a warning.
29691
- */
29692
- static async sendSupportTicketNotification(ticket) {
29693
- try {
29694
- const config = _getDashboardConfigInstance();
29695
- const endpointsConfig = config.endpoints ?? DEFAULT_ENDPOINTS_CONFIG;
29696
- const { slackWebhookUrl, slackProxyEndpoint } = endpointsConfig;
29697
- console.log("SlackAPI Debug - Configuration check:", {
29698
- hasConfig: !!config,
29699
- hasEndpoints: !!config.endpoints,
29700
- slackWebhookUrl: slackWebhookUrl ? "configured" : "not configured",
29701
- slackProxyEndpoint: slackProxyEndpoint ? "configured" : "not configured",
29702
- envVariable: process.env.SLACK_WEBHOOK_URL ? "set" : "not set",
29703
- publicEnvVariable: process.env.NEXT_PUBLIC_SLACK_WEBHOOK_URL ? "set" : "not set"
29704
- });
29705
- if (slackProxyEndpoint) {
29706
- const slackMessage = this.formatSlackMessage(ticket);
29707
- const response = await fetch(slackProxyEndpoint, {
29708
- method: "POST",
29709
- headers: {
29710
- "Content-Type": "application/json"
29711
- },
29712
- body: JSON.stringify(slackMessage)
29713
- });
29714
- if (!response.ok) {
29715
- const errorData = await response.json().catch(() => ({ message: "Unknown error" }));
29716
- throw new Error(errorData.message || `Proxy failed with status: ${response.status}`);
29717
- }
29718
- console.log("Support ticket notification sent to Slack successfully via proxy");
29719
- return;
29720
- }
29721
- if (slackWebhookUrl) {
29722
- const slackMessage = this.formatSlackMessage(ticket);
29723
- const response = await fetch(slackWebhookUrl, {
29724
- method: "POST",
29725
- headers: {
29726
- "Content-Type": "application/json"
29727
- },
29728
- body: JSON.stringify(slackMessage)
29729
- });
29730
- if (!response.ok) {
29731
- const errorText = await response.text();
29732
- console.error("Slack webhook error:", errorText);
29733
- throw new Error(`Slack webhook failed with status: ${response.status}`);
29734
- }
29735
- console.log("Support ticket notification sent to Slack successfully via webhook");
29736
- return;
29737
- }
29738
- console.warn("Slack notification skipped: No webhook or proxy endpoint configured");
29739
- console.info("To fix this, either:");
29740
- console.info("1. Set up a server-side proxy endpoint and configure slackProxyEndpoint in your dashboard config");
29741
- console.info("2. For development only: use NEXT_PUBLIC_SLACK_WEBHOOK_URL (not recommended for production)");
29742
- console.info("3. Configure the webhook URL directly in your dashboard config at runtime");
29743
- } catch (error) {
29744
- console.error("Failed to send Slack notification:", error);
29745
- throw error;
29746
- }
29747
- }
29748
- /**
29749
- * Formats a support ticket into a Slack message format
29750
- * This can be used by server-side implementations
29751
- */
29752
- static formatSlackMessage(ticket) {
29753
- const timestamp = new Date(ticket.timestamp).toLocaleString("en-US", {
29754
- dateStyle: "medium",
29755
- timeStyle: "short",
29756
- timeZone: "UTC"
29757
- });
29758
- const maxDescriptionLength = 300;
29759
- const description = ticket.description.length > maxDescriptionLength ? `${ticket.description.substring(0, maxDescriptionLength)}...` : ticket.description;
29760
- const categoryConfig = {
29761
- general: { emoji: "\u{1F4AC}", color: "#36a64f" },
29762
- technical: { emoji: "\u{1F527}", color: "#ff6b6b" },
29763
- feature: { emoji: "\u2728", color: "#4ecdc4" },
29764
- billing: { emoji: "\u{1F4B3}", color: "#f7b731" }
29765
- };
29766
- const priorityConfig = {
29767
- low: { emoji: "\u{1F7E2}", color: "#36a64f" },
29768
- normal: { emoji: "\u{1F7E1}", color: "#ffc107" },
29769
- high: { emoji: "\u{1F7E0}", color: "#ff8c00" },
29770
- urgent: { emoji: "\u{1F534}", color: "#dc3545" }
29771
- };
29772
- const categoryInfo = categoryConfig[ticket.category] || categoryConfig.general;
29773
- const priorityInfo = priorityConfig[ticket.priority] || priorityConfig.normal;
29774
- const messageColor = ticket.priority === "high" || ticket.priority === "urgent" ? priorityInfo.color : categoryInfo.color;
29775
- return {
29776
- text: `New support ticket from ${ticket.email}`,
29777
- blocks: [
29778
- {
29779
- type: "header",
29780
- text: {
29781
- type: "plain_text",
29782
- text: "\u{1F3AB} New Support Ticket Submitted",
29783
- emoji: true
29784
- }
29785
- },
29786
- {
29787
- type: "section",
29788
- fields: [
29789
- {
29790
- type: "mrkdwn",
29791
- text: `*From:*
29792
- ${ticket.email}`
29793
- },
29794
- {
29795
- type: "mrkdwn",
29796
- text: `*Category:*
29797
- ${categoryInfo.emoji} ${ticket.category.charAt(0).toUpperCase() + ticket.category.slice(1)}`
29798
- },
29799
- {
29800
- type: "mrkdwn",
29801
- text: `*Priority:*
29802
- ${priorityInfo.emoji} ${ticket.priority.charAt(0).toUpperCase() + ticket.priority.slice(1)}`
29803
- },
29804
- {
29805
- type: "mrkdwn",
29806
- text: `*Subject:*
29807
- ${ticket.subject}`
29808
- },
29809
- {
29810
- type: "mrkdwn",
29811
- text: `*Submitted:*
29812
- ${timestamp} UTC`
29813
- }
29814
- ]
29815
- },
29816
- {
29817
- type: "section",
29818
- text: {
29819
- type: "mrkdwn",
29820
- text: `*Description:*
29821
- ${description}`
29822
- }
29823
- },
29824
- {
29825
- type: "divider"
29826
- },
29827
- {
29828
- type: "context",
29829
- elements: [
29830
- {
29831
- type: "mrkdwn",
29832
- text: `Category: \`${ticket.category}\` | Priority: ${priorityInfo.emoji} \`${ticket.priority.toUpperCase()}\` | ${ticket.priority === "urgent" ? "\u26A0\uFE0F Requires immediate attention" : "Standard processing"}`
29833
- }
29834
- ]
29835
- }
29836
- ],
29837
- attachments: [
29838
- {
29839
- color: messageColor,
29840
- fields: []
29841
- }
29842
- ]
29843
- };
29844
- }
29845
- };
29846
29466
  var HelpView = ({
29847
29467
  onTicketSubmit,
29848
29468
  supportEmail = "support@optifye.com"
@@ -29907,11 +29527,6 @@ var HelpView = ({
29907
29527
  category: ticket.category,
29908
29528
  priority: ticket.priority
29909
29529
  });
29910
- try {
29911
- await SlackAPI.sendSupportTicketNotification(ticket);
29912
- } catch (slackError) {
29913
- console.error("Failed to send Slack notification:", slackError);
29914
- }
29915
29530
  if (onTicketSubmit) {
29916
29531
  await onTicketSubmit(ticket);
29917
29532
  } else {
@@ -35877,4 +35492,221 @@ var S3Service = class {
35877
35492
  }
35878
35493
  };
35879
35494
 
35880
- export { ACTION_NAMES, AIAgentView_default as AIAgentView, AuthCallback, AuthCallbackView_default as AuthCallbackView, AuthProvider, AuthenticatedFactoryView, AuthenticatedHelpView, AuthenticatedHomeView, AuthenticatedTargetsView, BarChart, BaseHistoryCalendar, BottlenecksContent, BreakNotificationPopup, Card2 as Card, CardContent2 as CardContent, CardDescription2 as CardDescription, CardFooter2 as CardFooter, CardHeader2 as CardHeader, CardTitle2 as CardTitle, CycleTimeChart, CycleTimeOverTimeChart, DEFAULT_ANALYTICS_CONFIG, DEFAULT_AUTH_CONFIG, DEFAULT_CONFIG, DEFAULT_DATABASE_CONFIG, DEFAULT_DATE_TIME_CONFIG, DEFAULT_ENDPOINTS_CONFIG, DEFAULT_ENTITY_CONFIG, DEFAULT_SHIFT_CONFIG, DEFAULT_THEME_CONFIG, DEFAULT_VIDEO_CONFIG, DEFAULT_WORKSPACE_CONFIG, DEFAULT_WORKSPACE_POSITIONS, DashboardHeader, DashboardLayout, DashboardOverridesProvider, DashboardProvider, DateDisplay_default as DateDisplay, DateTimeDisplay, DebugAuth, DebugAuthView_default as DebugAuthView, EmptyStateMessage, FactoryView_default as FactoryView, GaugeChart, GridComponentsPlaceholder, HamburgerButton, Header, HelpView_default as HelpView, HomeView_default as HomeView, HourlyOutputChart2 as HourlyOutputChart, ISTTimer_default as ISTTimer, KPICard, KPIDetailView_default as KPIDetailView, KPIGrid, KPIHeader, KPISection, KPIsOverviewView_default as KPIsOverviewView, LINE_1_UUID, LINE_2_UUID, LargeOutputProgressChart, LeaderboardDetailView_default as LeaderboardDetailView, Legend6 as Legend, LineChart, LineHistoryCalendar, LineMonthlyHistory, LineMonthlyPdfGenerator, LinePdfExportButton, LinePdfGenerator, LineWhatsAppShareButton, LiveTimer, LoadingInline, LoadingOverlay_default as LoadingOverlay, LoadingPage_default as LoadingPage, LoadingSkeleton, LoadingState, LoginPage, LoginView_default as LoginView, MainLayout, MetricCard_default as MetricCard, NoWorkspaceData, OptifyeAgentClient, OptifyeLogoLoader_default as OptifyeLogoLoader, OutputProgressChart, PageHeader, PieChart4 as PieChart, ProfileView_default as ProfileView, RegistryProvider, S3Service, SKUManagementView, SOPComplianceChart, SSEChatClient, Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectScrollDownButton, SelectScrollUpButton, SelectSeparator, SelectTrigger, SelectValue, ShiftDisplay_default as ShiftDisplay, ShiftsView_default as ShiftsView, SideNavBar, SingleVideoStream_default as SingleVideoStream, Skeleton, SlackAPI, SubscriptionManager, SubscriptionManagerProvider, SupabaseProvider, TargetWorkspaceGrid, TargetsView_default as TargetsView, ThreadSidebar, TicketHistory_default as TicketHistory, TicketHistoryService, TimeDisplay_default as TimeDisplay, TimePickerDropdown, VideoCard, VideoGridView, VideoPlayer, VideoPreloader, WORKSPACE_POSITIONS, WhatsAppShareButton, WorkspaceCard, WorkspaceDetailView_default as WorkspaceDetailView, WorkspaceDisplayNameExample, WorkspaceGrid, WorkspaceGridItem, WorkspaceHistoryCalendar, WorkspaceMetricCards, WorkspaceMonthlyDataFetcher, WorkspaceMonthlyPdfGenerator, WorkspacePdfExportButton, WorkspacePdfGenerator, WorkspaceWhatsAppShareButton, actionService, apiUtils, authCoreService, authOTPService, authRateLimitService, cacheService, checkRateLimit2 as checkRateLimit, clearAllRateLimits2 as clearAllRateLimits, clearRateLimit2 as clearRateLimit, clearS3VideoCache, clearS3VideoFromCache, clearWorkspaceDisplayNamesCache, cn, createStreamProxyHandler, createSupabaseClient, createThrottledReload, dashboardService, deleteThread, forceRefreshWorkspaceDisplayNames, formatDateInZone, formatDateTimeInZone, formatISTDate, formatIdleTime, formatTimeInZone, fromUrlFriendlyName, getAllLineDisplayNames, getAllThreadMessages, getAllWorkspaceDisplayNamesAsync, getAnonClient, getCameraNumber, getCompanyMetricsTableName, getConfigurableShortWorkspaceDisplayName, getConfigurableWorkspaceDisplayName, getConfiguredLineIds, getCoreSessionRecordingProperties, getCoreSessionReplayUrl, getCurrentShift, getCurrentTimeInZone, getDashboardHeaderTimeInZone, getDaysDifferenceInZone, getDefaultCameraStreamUrl, getDefaultLineId, getDefaultTabForWorkspace, getLineDisplayName, getManufacturingInsights, getMetricsTablePrefix, getOperationalDate, getS3SignedUrl, getS3VideoSrc, getShortWorkspaceDisplayName, getShortWorkspaceDisplayNameAsync, getStoredWorkspaceMappings, getSubscriptionManager, getThreadMessages, getUserThreads, getUserThreadsPaginated, getWorkspaceDisplayName, getWorkspaceDisplayNameAsync, getWorkspaceDisplayNamesMap, getWorkspaceFromUrl, getWorkspaceNavigationParams, identifyCoreUser, initializeCoreMixpanel, isLegacyConfiguration, isTransitionPeriod, isUrlPermanentlyFailed, isValidFactoryViewConfiguration, isValidLineInfoPayload, isValidWorkspaceDetailedMetricsPayload, isValidWorkspaceMetricsPayload, isWorkspaceDisplayNamesLoaded, isWorkspaceDisplayNamesLoading, mergeWithDefaultConfig, migrateLegacyConfiguration, optifyeAgentClient, preInitializeWorkspaceDisplayNames, preloadS3Video, preloadS3VideoUrl, preloadS3VideosUrl, preloadVideoUrl, preloadVideosUrl, qualityService, realtimeService, refreshWorkspaceDisplayNames, resetCoreMixpanel, resetFailedUrl, resetSubscriptionManager, s3VideoPreloader, skuService, startCoreSessionRecording, stopCoreSessionRecording, storeWorkspaceMapping, streamProxyConfig, throttledReloadDashboard, toUrlFriendlyName, trackCoreEvent, trackCorePageView, updateThreadTitle, useActiveBreaks, useAllWorkspaceMetrics, useAnalyticsConfig, useAuth, useAuthConfig, useComponentOverride, useCustomConfig, useDashboardConfig, useDashboardMetrics, useDatabaseConfig, useDateFormatter, useDateTimeConfig, useEndpointsConfig, useEntityConfig, useFactoryOverviewMetrics, useFeatureFlags, useFormatNumber, useHistoricWorkspaceMetrics, useHlsStream, useHlsStreamWithCropping, useHookOverride, useLeaderboardMetrics, useLineDetailedMetrics, useLineKPIs, useLineMetrics, useLineWorkspaceMetrics, useMessages, useMetrics, useNavigation, useOverrides, usePageOverride, usePrefetchClipCounts, useRealtimeLineMetrics, useRegistry, useSKUs, useShiftConfig, useShifts, useSubscriptionManager, useSubscriptionManagerSafe, useSupabase, useSupabaseClient, useTargets, useTheme, useThemeConfig, useThreads, useTicketHistory, useVideoConfig, useWorkspaceConfig, useWorkspaceDetailedMetrics, useWorkspaceDisplayName, useWorkspaceDisplayNames, useWorkspaceDisplayNamesMap, useWorkspaceMetrics, useWorkspaceNavigation, useWorkspaceOperators, videoPreloader, whatsappService, withAuth, withRegistry, workspaceService };
35495
+ // src/lib/api/optifye-agent.ts
35496
+ var OPTIFYE_API_URL = "https://optifye-agent-production.up.railway.app";
35497
+ var OptifyeAgentClient = class {
35498
+ constructor(apiUrl = OPTIFYE_API_URL) {
35499
+ this.apiUrl = apiUrl;
35500
+ }
35501
+ /**
35502
+ * Call Optifye Agent for manufacturing analysis
35503
+ */
35504
+ async getManufacturingInsights(userQuestion, lineId, shiftId, companyId, context) {
35505
+ try {
35506
+ const requestData = {
35507
+ prompt: userQuestion,
35508
+ line_id: lineId,
35509
+ shift_id: shiftId,
35510
+ company_id: companyId
35511
+ };
35512
+ if (context) {
35513
+ requestData.context = context;
35514
+ }
35515
+ console.log("[OptifyeAgent] Sending request:", requestData);
35516
+ const response = await fetch(`${this.apiUrl}/api/custom-analysis`, {
35517
+ method: "POST",
35518
+ headers: {
35519
+ "Content-Type": "application/json"
35520
+ },
35521
+ body: JSON.stringify(requestData),
35522
+ signal: AbortSignal.timeout(6e4)
35523
+ // 60 second timeout
35524
+ });
35525
+ const responseText = await response.text();
35526
+ console.log("[OptifyeAgent] Response status:", response.status);
35527
+ console.log("[OptifyeAgent] Response text:", responseText);
35528
+ let result;
35529
+ try {
35530
+ result = JSON.parse(responseText);
35531
+ } catch (parseError) {
35532
+ console.error("[OptifyeAgent] Failed to parse response as JSON:", parseError);
35533
+ if (responseText.includes("'Agent' object has no attribute")) {
35534
+ return {
35535
+ success: false,
35536
+ error: "Server error: The AI agent service is experiencing issues. Please try again later or contact support."
35537
+ };
35538
+ }
35539
+ return {
35540
+ success: false,
35541
+ error: `Invalid response format from server: ${responseText.substring(0, 200)}`
35542
+ };
35543
+ }
35544
+ if (response.ok) {
35545
+ return {
35546
+ success: result.success ?? true,
35547
+ analysis: result.analysis || result.response || result.message || result.data,
35548
+ timestamp: result.timestamp,
35549
+ error: result.error
35550
+ };
35551
+ } else {
35552
+ const errorMsg = result.error || result.message || `API request failed: ${response.status}`;
35553
+ console.error("[OptifyeAgent] API error:", errorMsg);
35554
+ if (errorMsg.includes("'Agent' object has no attribute")) {
35555
+ return {
35556
+ success: false,
35557
+ error: "The AI service is currently being updated. Please try again in a few moments."
35558
+ };
35559
+ }
35560
+ return {
35561
+ success: false,
35562
+ error: errorMsg
35563
+ };
35564
+ }
35565
+ } catch (error) {
35566
+ const errorMsg = error instanceof Error ? `Failed to connect to Optifye Agent: ${error.message}` : "Failed to connect to Optifye Agent";
35567
+ console.error("[OptifyeAgent] Request failed:", error);
35568
+ if (error instanceof Error && error.name === "AbortError") {
35569
+ return {
35570
+ success: false,
35571
+ error: "Request timed out. The AI agent is taking too long to respond. Please try again."
35572
+ };
35573
+ }
35574
+ return {
35575
+ success: false,
35576
+ error: errorMsg
35577
+ };
35578
+ }
35579
+ }
35580
+ /**
35581
+ * Check if Optifye Agent API is healthy
35582
+ */
35583
+ async checkHealth() {
35584
+ try {
35585
+ const response = await fetch(`${this.apiUrl}/health`, {
35586
+ signal: AbortSignal.timeout(1e4)
35587
+ // 10 second timeout
35588
+ });
35589
+ if (response.ok) {
35590
+ const healthData = await response.json();
35591
+ return healthData.status === "healthy";
35592
+ }
35593
+ return false;
35594
+ } catch (error) {
35595
+ console.error("[OptifyeAgent] Health check failed:", error);
35596
+ return false;
35597
+ }
35598
+ }
35599
+ };
35600
+ var optifyeAgentClient = new OptifyeAgentClient();
35601
+ async function getManufacturingInsights(userQuestion, lineId, shiftId, companyId, context) {
35602
+ if (!userQuestion || !userQuestion.trim()) {
35603
+ return {
35604
+ success: false,
35605
+ error: "Please provide a question"
35606
+ };
35607
+ }
35608
+ if (!lineId || !companyId) {
35609
+ console.warn("[OptifyeAgent] Missing required IDs:", { lineId, companyId });
35610
+ }
35611
+ return optifyeAgentClient.getManufacturingInsights(
35612
+ userQuestion,
35613
+ lineId,
35614
+ shiftId,
35615
+ companyId,
35616
+ context
35617
+ );
35618
+ }
35619
+ function createStreamProxyHandler(config) {
35620
+ const cloudFrontDomain = config?.cloudFrontDomain || "https://d1eiob0chi5jw.cloudfront.net";
35621
+ return async function handler(req, res) {
35622
+ if (req.method !== "GET") {
35623
+ return res.status(405).json({ error: "Method not allowed" });
35624
+ }
35625
+ const { path } = req.query;
35626
+ if (!path || !Array.isArray(path)) {
35627
+ return res.status(400).json({ error: "Missing path parameter" });
35628
+ }
35629
+ const fullPath = path.join("/");
35630
+ const targetUrl = `${cloudFrontDomain}/${fullPath}`;
35631
+ try {
35632
+ console.log(`[HLS Stream Proxy] Streaming: ${targetUrl}`);
35633
+ const response = await fetch(targetUrl, {
35634
+ method: "GET",
35635
+ headers: {
35636
+ "User-Agent": "NextJS-HLS-Stream-Proxy",
35637
+ // Pass through range headers for partial content requests
35638
+ ...req.headers.range && { "Range": req.headers.range }
35639
+ }
35640
+ });
35641
+ if (!response.ok) {
35642
+ console.error(`[HLS Stream Proxy] CloudFront error: ${response.status} ${response.statusText}`);
35643
+ return res.status(response.status).json({
35644
+ error: `CloudFront request failed: ${response.statusText}`
35645
+ });
35646
+ }
35647
+ const contentType = response.headers.get("content-type") || "application/octet-stream";
35648
+ const contentLength = response.headers.get("content-length");
35649
+ res.setHeader("Access-Control-Allow-Origin", "*");
35650
+ res.setHeader("Access-Control-Allow-Methods", "GET, HEAD");
35651
+ res.setHeader("Access-Control-Allow-Headers", "Content-Type, Range");
35652
+ res.setHeader("Access-Control-Expose-Headers", "Content-Length, Content-Range");
35653
+ res.setHeader("Content-Type", contentType);
35654
+ if (contentLength) {
35655
+ res.setHeader("Content-Length", contentLength);
35656
+ }
35657
+ if (fullPath.endsWith(".m3u8")) {
35658
+ res.setHeader("Content-Type", "application/vnd.apple.mpegurl");
35659
+ } else if (fullPath.endsWith(".ts")) {
35660
+ res.setHeader("Content-Type", "video/mp2t");
35661
+ }
35662
+ if (response.status === 206) {
35663
+ res.status(206);
35664
+ const contentRange = response.headers.get("content-range");
35665
+ if (contentRange) {
35666
+ res.setHeader("Content-Range", contentRange);
35667
+ }
35668
+ res.setHeader("Accept-Ranges", "bytes");
35669
+ }
35670
+ if (response.body) {
35671
+ const reader = response.body.getReader();
35672
+ const nodeStream = new Readable({
35673
+ async read() {
35674
+ try {
35675
+ const { done, value } = await reader.read();
35676
+ if (done) {
35677
+ this.push(null);
35678
+ } else {
35679
+ this.push(Buffer.from(value));
35680
+ }
35681
+ } catch (error) {
35682
+ console.error("[HLS Stream Proxy] Stream read error:", error);
35683
+ this.destroy(error);
35684
+ }
35685
+ }
35686
+ });
35687
+ nodeStream.pipe(res);
35688
+ req.on("close", () => {
35689
+ reader.cancel();
35690
+ nodeStream.destroy();
35691
+ });
35692
+ } else {
35693
+ const buffer = await response.arrayBuffer();
35694
+ res.send(Buffer.from(buffer));
35695
+ }
35696
+ } catch (error) {
35697
+ console.error("[HLS Stream Proxy] Error:", error);
35698
+ res.status(500).json({
35699
+ error: "Failed to stream from CloudFront",
35700
+ details: error instanceof Error ? error.message : String(error)
35701
+ });
35702
+ }
35703
+ };
35704
+ }
35705
+ var streamProxyConfig = {
35706
+ api: {
35707
+ bodyParser: false,
35708
+ responseLimit: false
35709
+ }
35710
+ };
35711
+
35712
+ export { ACTION_NAMES, AIAgentView_default as AIAgentView, AuthCallback, AuthCallbackView_default as AuthCallbackView, AuthProvider, AuthenticatedFactoryView, AuthenticatedHelpView, AuthenticatedHomeView, AuthenticatedTargetsView, BarChart, BaseHistoryCalendar, BottlenecksContent, BreakNotificationPopup, Card2 as Card, CardContent2 as CardContent, CardDescription2 as CardDescription, CardFooter2 as CardFooter, CardHeader2 as CardHeader, CardTitle2 as CardTitle, CycleTimeChart, CycleTimeOverTimeChart, DEFAULT_ANALYTICS_CONFIG, DEFAULT_AUTH_CONFIG, DEFAULT_CONFIG, DEFAULT_DATABASE_CONFIG, DEFAULT_DATE_TIME_CONFIG, DEFAULT_ENDPOINTS_CONFIG, DEFAULT_ENTITY_CONFIG, DEFAULT_SHIFT_CONFIG, DEFAULT_THEME_CONFIG, DEFAULT_VIDEO_CONFIG, DEFAULT_WORKSPACE_CONFIG, DEFAULT_WORKSPACE_POSITIONS, DashboardHeader, DashboardLayout, DashboardOverridesProvider, DashboardProvider, DateDisplay_default as DateDisplay, DateTimeDisplay, DebugAuth, DebugAuthView_default as DebugAuthView, EmptyStateMessage, FactoryView_default as FactoryView, GaugeChart, GridComponentsPlaceholder, HamburgerButton, Header, HelpView_default as HelpView, HomeView_default as HomeView, HourlyOutputChart2 as HourlyOutputChart, ISTTimer_default as ISTTimer, KPICard, KPIDetailView_default as KPIDetailView, KPIGrid, KPIHeader, KPISection, KPIsOverviewView_default as KPIsOverviewView, LINE_1_UUID, LINE_2_UUID, LargeOutputProgressChart, LeaderboardDetailView_default as LeaderboardDetailView, Legend6 as Legend, LineChart, LineHistoryCalendar, LineMonthlyHistory, LineMonthlyPdfGenerator, LinePdfExportButton, LinePdfGenerator, LineWhatsAppShareButton, LiveTimer, LoadingInline, LoadingOverlay_default as LoadingOverlay, LoadingPage_default as LoadingPage, LoadingSkeleton, LoadingState, LoginPage, LoginView_default as LoginView, MainLayout, MetricCard_default as MetricCard, NoWorkspaceData, OptifyeAgentClient, OptifyeLogoLoader_default as OptifyeLogoLoader, OutputProgressChart, PageHeader, PieChart4 as PieChart, ProfileView_default as ProfileView, RegistryProvider, S3Service, SKUManagementView, SOPComplianceChart, SSEChatClient, Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectScrollDownButton, SelectScrollUpButton, SelectSeparator, SelectTrigger, SelectValue, ShiftDisplay_default as ShiftDisplay, ShiftsView_default as ShiftsView, SideNavBar, SingleVideoStream_default as SingleVideoStream, Skeleton, SubscriptionManager, SubscriptionManagerProvider, SupabaseProvider, TargetWorkspaceGrid, TargetsView_default as TargetsView, ThreadSidebar, TicketHistory_default as TicketHistory, TicketHistoryService, TimeDisplay_default as TimeDisplay, TimePickerDropdown, VideoCard, VideoGridView, VideoPlayer, VideoPreloader, WORKSPACE_POSITIONS, WhatsAppShareButton, WorkspaceCard, WorkspaceDetailView_default as WorkspaceDetailView, WorkspaceDisplayNameExample, WorkspaceGrid, WorkspaceGridItem, WorkspaceHistoryCalendar, WorkspaceMetricCards, WorkspaceMonthlyDataFetcher, WorkspaceMonthlyPdfGenerator, WorkspacePdfExportButton, WorkspacePdfGenerator, WorkspaceWhatsAppShareButton, actionService, apiUtils, authCoreService, authOTPService, authRateLimitService, cacheService, checkRateLimit2 as checkRateLimit, clearAllRateLimits2 as clearAllRateLimits, clearRateLimit2 as clearRateLimit, clearS3VideoCache, clearS3VideoFromCache, clearWorkspaceDisplayNamesCache, cn, createStreamProxyHandler, createSupabaseClient, createThrottledReload, dashboardService, deleteThread, forceRefreshWorkspaceDisplayNames, formatDateInZone, formatDateTimeInZone, formatISTDate, formatIdleTime, formatTimeInZone, fromUrlFriendlyName, getAllLineDisplayNames, getAllThreadMessages, getAllWorkspaceDisplayNamesAsync, getAnonClient, getCameraNumber, getCompanyMetricsTableName, getConfigurableShortWorkspaceDisplayName, getConfigurableWorkspaceDisplayName, getConfiguredLineIds, getCoreSessionRecordingProperties, getCoreSessionReplayUrl, getCurrentShift, getCurrentTimeInZone, getDashboardHeaderTimeInZone, getDaysDifferenceInZone, getDefaultCameraStreamUrl, getDefaultLineId, getDefaultTabForWorkspace, getLineDisplayName, getManufacturingInsights, getMetricsTablePrefix, getOperationalDate, getS3SignedUrl, getS3VideoSrc, getShortWorkspaceDisplayName, getShortWorkspaceDisplayNameAsync, getStoredWorkspaceMappings, getSubscriptionManager, getThreadMessages, getUserThreads, getUserThreadsPaginated, getWorkspaceDisplayName, getWorkspaceDisplayNameAsync, getWorkspaceDisplayNamesMap, getWorkspaceFromUrl, getWorkspaceNavigationParams, identifyCoreUser, initializeCoreMixpanel, isLegacyConfiguration, isTransitionPeriod, isUrlPermanentlyFailed, isValidFactoryViewConfiguration, isValidLineInfoPayload, isValidWorkspaceDetailedMetricsPayload, isValidWorkspaceMetricsPayload, isWorkspaceDisplayNamesLoaded, isWorkspaceDisplayNamesLoading, mergeWithDefaultConfig, migrateLegacyConfiguration, optifyeAgentClient, preInitializeWorkspaceDisplayNames, preloadS3Video, preloadS3VideoUrl, preloadS3VideosUrl, preloadVideoUrl, preloadVideosUrl, qualityService, realtimeService, refreshWorkspaceDisplayNames, resetCoreMixpanel, resetFailedUrl, resetSubscriptionManager, s3VideoPreloader, skuService, startCoreSessionRecording, stopCoreSessionRecording, storeWorkspaceMapping, streamProxyConfig, throttledReloadDashboard, toUrlFriendlyName, trackCoreEvent, trackCorePageView, updateThreadTitle, useActiveBreaks, useAllWorkspaceMetrics, useAnalyticsConfig, useAuth, useAuthConfig, useComponentOverride, useCustomConfig, useDashboardConfig, useDashboardMetrics, useDatabaseConfig, useDateFormatter, useDateTimeConfig, useEndpointsConfig, useEntityConfig, useFactoryOverviewMetrics, useFeatureFlags, useFormatNumber, useHistoricWorkspaceMetrics, useHlsStream, useHlsStreamWithCropping, useHookOverride, useLeaderboardMetrics, useLineDetailedMetrics, useLineKPIs, useLineMetrics, useLineWorkspaceMetrics, useMessages, useMetrics, useNavigation, useOverrides, usePageOverride, usePrefetchClipCounts, useRealtimeLineMetrics, useRegistry, useSKUs, useShiftConfig, useShifts, useSubscriptionManager, useSubscriptionManagerSafe, useSupabase, useSupabaseClient, useTargets, useTheme, useThemeConfig, useThreads, useTicketHistory, useVideoConfig, useWorkspaceConfig, useWorkspaceDetailedMetrics, useWorkspaceDisplayName, useWorkspaceDisplayNames, useWorkspaceDisplayNamesMap, useWorkspaceMetrics, useWorkspaceNavigation, useWorkspaceOperators, videoPreloader, whatsappService, withAuth, withRegistry, workspaceService };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@optifye/dashboard-core",
3
- "version": "6.2.0",
3
+ "version": "6.3.1",
4
4
  "description": "Reusable UI & logic for Optifye dashboard",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",
@@ -67,6 +67,7 @@
67
67
  "@types/mixpanel-browser": "^2.51.0",
68
68
  "@types/react": "^19.0.4",
69
69
  "@types/react-dom": "^19.0.2",
70
+ "@types/video.js": "^7.3.58",
70
71
  "autoprefixer": "^10.4.21",
71
72
  "postcss": "^8.5.6",
72
73
  "tsup": "^8.0.2",