@optifye/dashboard-core 4.3.6 → 4.3.9

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.d.mts CHANGED
@@ -903,7 +903,7 @@ interface BottleneckVideoData {
903
903
  timestamp: string;
904
904
  severity: 'low' | 'medium' | 'high';
905
905
  description: string;
906
- type: 'bottleneck' | 'low_value' | 'best_cycle_time' | 'worst_cycle_time' | 'missing_quality_check';
906
+ type: 'bottleneck' | 'low_value' | 'best_cycle_time' | 'worst_cycle_time' | 'missing_quality_check' | 'cycle_completions';
907
907
  originalUri: string;
908
908
  cycle_time_seconds?: number;
909
909
  creation_timestamp?: string;
@@ -959,7 +959,7 @@ interface VideoMetadata {
959
959
  creation_timestamp?: string;
960
960
  [key: string]: any;
961
961
  }
962
- type VideoType = 'bottleneck' | 'low_value' | 'best_cycle_time' | 'worst_cycle_time' | 'missing_quality_check';
962
+ type VideoType = 'bottleneck' | 'low_value' | 'best_cycle_time' | 'worst_cycle_time' | 'missing_quality_check' | 'cycle_completions';
963
963
  type VideoSeverity = 'low' | 'medium' | 'high';
964
964
 
965
965
  interface ChatThread {
@@ -2352,10 +2352,11 @@ declare const resetCoreMixpanel: () => void;
2352
2352
  * through SSE for the AI's response generation.
2353
2353
  *
2354
2354
  * Event flow:
2355
- * 1. POST message to /api/chat endpoint
2356
- * 2. Receive SSE stream with events: thread, message, reasoning, complete, error
2355
+ * 1. POST message to /api/v2/chat endpoint
2356
+ * 2. Receive SSE stream with events: thread, message, tool_call, tool_result, complete, error
2357
2357
  * 3. AI response is streamed in chunks via 'message' events
2358
- * 4. Once complete, the full conversation is persisted in Supabase
2358
+ * 4. Tool calls and results are visible in real-time
2359
+ * 5. Once complete, the full conversation is persisted in Supabase
2359
2360
  */
2360
2361
  declare class SSEChatClient {
2361
2362
  private controllers;
@@ -2369,7 +2370,9 @@ declare class SSEChatClient {
2369
2370
  onThreadCreated?: (threadId: string) => void;
2370
2371
  onMessage?: (text: string) => void;
2371
2372
  onReasoning?: (text: string) => void;
2372
- onComplete?: (messageId: number) => void;
2373
+ onToolCall?: (tools: any[]) => void;
2374
+ onToolResult?: (results: any[]) => void;
2375
+ onComplete?: (messageId: number, metrics?: any) => void;
2373
2376
  onError?: (error: string) => void;
2374
2377
  }): Promise<void>;
2375
2378
  private handleSSEStream;
@@ -3465,7 +3468,7 @@ interface BottlenecksContentProps {
3465
3468
  /**
3466
3469
  * Filter type for bottleneck clips - expanded for new video types
3467
3470
  */
3468
- type BottleneckFilterType = 'all' | 'high' | 'medium' | 'low' | 'low_value' | 'sop_deviations' | 'best_cycle_time' | 'worst_cycle_time' | 'long_cycle_time';
3471
+ type BottleneckFilterType = 'all' | 'high' | 'medium' | 'low' | 'low_value' | 'sop_deviations' | 'best_cycle_time' | 'worst_cycle_time' | 'long_cycle_time' | 'cycle_completions';
3469
3472
  /**
3470
3473
  * Clip counts for each type/severity - updated for new video types
3471
3474
  */
@@ -3478,6 +3481,8 @@ interface ClipCounts {
3478
3481
  sopDeviations: number;
3479
3482
  bestCycleTimes: number;
3480
3483
  worstCycleTimes: number;
3484
+ longCycleTimes: number;
3485
+ cycleCompletions: number;
3481
3486
  total: number;
3482
3487
  }
3483
3488
 
package/dist/index.d.ts CHANGED
@@ -903,7 +903,7 @@ interface BottleneckVideoData {
903
903
  timestamp: string;
904
904
  severity: 'low' | 'medium' | 'high';
905
905
  description: string;
906
- type: 'bottleneck' | 'low_value' | 'best_cycle_time' | 'worst_cycle_time' | 'missing_quality_check';
906
+ type: 'bottleneck' | 'low_value' | 'best_cycle_time' | 'worst_cycle_time' | 'missing_quality_check' | 'cycle_completions';
907
907
  originalUri: string;
908
908
  cycle_time_seconds?: number;
909
909
  creation_timestamp?: string;
@@ -959,7 +959,7 @@ interface VideoMetadata {
959
959
  creation_timestamp?: string;
960
960
  [key: string]: any;
961
961
  }
962
- type VideoType = 'bottleneck' | 'low_value' | 'best_cycle_time' | 'worst_cycle_time' | 'missing_quality_check';
962
+ type VideoType = 'bottleneck' | 'low_value' | 'best_cycle_time' | 'worst_cycle_time' | 'missing_quality_check' | 'cycle_completions';
963
963
  type VideoSeverity = 'low' | 'medium' | 'high';
964
964
 
965
965
  interface ChatThread {
@@ -2352,10 +2352,11 @@ declare const resetCoreMixpanel: () => void;
2352
2352
  * through SSE for the AI's response generation.
2353
2353
  *
2354
2354
  * Event flow:
2355
- * 1. POST message to /api/chat endpoint
2356
- * 2. Receive SSE stream with events: thread, message, reasoning, complete, error
2355
+ * 1. POST message to /api/v2/chat endpoint
2356
+ * 2. Receive SSE stream with events: thread, message, tool_call, tool_result, complete, error
2357
2357
  * 3. AI response is streamed in chunks via 'message' events
2358
- * 4. Once complete, the full conversation is persisted in Supabase
2358
+ * 4. Tool calls and results are visible in real-time
2359
+ * 5. Once complete, the full conversation is persisted in Supabase
2359
2360
  */
2360
2361
  declare class SSEChatClient {
2361
2362
  private controllers;
@@ -2369,7 +2370,9 @@ declare class SSEChatClient {
2369
2370
  onThreadCreated?: (threadId: string) => void;
2370
2371
  onMessage?: (text: string) => void;
2371
2372
  onReasoning?: (text: string) => void;
2372
- onComplete?: (messageId: number) => void;
2373
+ onToolCall?: (tools: any[]) => void;
2374
+ onToolResult?: (results: any[]) => void;
2375
+ onComplete?: (messageId: number, metrics?: any) => void;
2373
2376
  onError?: (error: string) => void;
2374
2377
  }): Promise<void>;
2375
2378
  private handleSSEStream;
@@ -3465,7 +3468,7 @@ interface BottlenecksContentProps {
3465
3468
  /**
3466
3469
  * Filter type for bottleneck clips - expanded for new video types
3467
3470
  */
3468
- type BottleneckFilterType = 'all' | 'high' | 'medium' | 'low' | 'low_value' | 'sop_deviations' | 'best_cycle_time' | 'worst_cycle_time' | 'long_cycle_time';
3471
+ type BottleneckFilterType = 'all' | 'high' | 'medium' | 'low' | 'low_value' | 'sop_deviations' | 'best_cycle_time' | 'worst_cycle_time' | 'long_cycle_time' | 'cycle_completions';
3469
3472
  /**
3470
3473
  * Clip counts for each type/severity - updated for new video types
3471
3474
  */
@@ -3478,6 +3481,8 @@ interface ClipCounts {
3478
3481
  sopDeviations: number;
3479
3482
  bestCycleTimes: number;
3480
3483
  worstCycleTimes: number;
3484
+ longCycleTimes: number;
3485
+ cycleCompletions: number;
3481
3486
  total: number;
3482
3487
  }
3483
3488
 
package/dist/index.js CHANGED
@@ -1905,8 +1905,8 @@ var SSEChatClient = class {
1905
1905
  user_id: userId,
1906
1906
  context
1907
1907
  });
1908
- const agnoApiUrl = this.baseUrl || "https://optifye-agent-production.up.railway.app";
1909
- const endpoint = `${agnoApiUrl}/api/chat`;
1908
+ const agnoApiUrl = this.baseUrl || "https://fastapi-production-111f9.up.railway.app";
1909
+ const endpoint = `${agnoApiUrl}/api/v2/chat`;
1910
1910
  console.log("[SSEClient] Posting directly to AGNO:", endpoint);
1911
1911
  const response = await fetch(endpoint, {
1912
1912
  method: "POST",
@@ -1964,7 +1964,7 @@ var SSEChatClient = class {
1964
1964
  const decoder = new TextDecoder();
1965
1965
  let buffer = "";
1966
1966
  try {
1967
- console.log("[SSEClient] Starting to read stream...");
1967
+ console.log("[SSEClient] Starting to read enhanced stream...");
1968
1968
  while (true) {
1969
1969
  const { done, value } = await reader.read();
1970
1970
  if (done) {
@@ -1994,11 +1994,14 @@ var SSEChatClient = class {
1994
1994
  case "message":
1995
1995
  callbacks.onMessage?.(data.text);
1996
1996
  break;
1997
- case "reasoning":
1998
- callbacks.onReasoning?.(data.text);
1997
+ case "tool_call":
1998
+ callbacks.onToolCall?.(data.tools);
1999
+ break;
2000
+ case "tool_result":
2001
+ callbacks.onToolResult?.(data.results);
1999
2002
  break;
2000
2003
  case "complete":
2001
- callbacks.onComplete?.(data.message_id);
2004
+ callbacks.onComplete?.(data.message_id, data.metrics);
2002
2005
  break;
2003
2006
  case "error":
2004
2007
  callbacks.onError?.(data.error);
@@ -21331,6 +21334,14 @@ function parseS3Uri(s3Uri) {
21331
21334
  severity = "high";
21332
21335
  description = "Worst Cycle Time Performance";
21333
21336
  break;
21337
+ case "cycle_completions":
21338
+ case "cycle_completion":
21339
+ case "completed_cycles":
21340
+ case "completed_cycle":
21341
+ type = "cycle_completions";
21342
+ severity = "low";
21343
+ description = "Cycle Completion";
21344
+ break;
21334
21345
  case "medium_bottleneck":
21335
21346
  severity = "medium";
21336
21347
  description = "Medium Bottleneck Identified";
@@ -21357,6 +21368,10 @@ function parseS3Uri(s3Uri) {
21357
21368
  type = "bottleneck";
21358
21369
  severity = "high";
21359
21370
  description = "Long Cycle Time Detected";
21371
+ } else if (normalizedViolationType.includes("cycle") && (normalizedViolationType.includes("completion") || normalizedViolationType.includes("complete"))) {
21372
+ type = "cycle_completions";
21373
+ severity = "low";
21374
+ description = "Cycle Completion";
21360
21375
  } else {
21361
21376
  description = `Clip type: ${violationType.replace(/_/g, " ")}`;
21362
21377
  console.log(`Detected unknown violation type: ${violationType} in URI: ${s3Uri}`);
@@ -21536,7 +21551,7 @@ var S3ClipsService = class {
21536
21551
  }
21537
21552
  let cycleTimeSeconds = null;
21538
21553
  let creationTimestamp = void 0;
21539
- if (includeMetadata || includeCycleTime && (parsedInfo.type === "bottleneck" && parsedInfo.description.toLowerCase().includes("cycle time") || parsedInfo.type === "best_cycle_time" || parsedInfo.type === "worst_cycle_time")) {
21554
+ if (includeMetadata || includeCycleTime && (parsedInfo.type === "bottleneck" && parsedInfo.description.toLowerCase().includes("cycle time") || parsedInfo.type === "best_cycle_time" || parsedInfo.type === "worst_cycle_time" || parsedInfo.type === "cycle_completions")) {
21540
21555
  const metadata = await this.getFullMetadata(uri);
21541
21556
  if (metadata) {
21542
21557
  if (metadata.original_task_metadata?.cycle_time) {
@@ -21569,6 +21584,7 @@ var S3ClipsService = class {
21569
21584
  low_value: 0,
21570
21585
  long_cycle_time: 0,
21571
21586
  missing_quality_check: 0,
21587
+ cycle_completions: 0,
21572
21588
  total: 0
21573
21589
  };
21574
21590
  const samples = {
@@ -21577,7 +21593,8 @@ var S3ClipsService = class {
21577
21593
  bottleneck: null,
21578
21594
  low_value: null,
21579
21595
  long_cycle_time: null,
21580
- missing_quality_check: null
21596
+ missing_quality_check: null,
21597
+ cycle_completions: null
21581
21598
  };
21582
21599
  for (const uri of s3Uris) {
21583
21600
  const parsedInfo = parseS3Uri(uri);
@@ -21865,6 +21882,7 @@ var BottlenecksContent = ({
21865
21882
  const firstBestCycle = videos.find((v) => v.type === "best_cycle_time");
21866
21883
  const firstWorstCycle = videos.find((v) => v.type === "worst_cycle_time");
21867
21884
  const firstSOPDeviation = videos.find((v) => v.type === "missing_quality_check");
21885
+ const firstCycleCompletion = videos.find((v) => v.type === "cycle_completions");
21868
21886
  preloadVideosUrl2([
21869
21887
  firstHigh?.src,
21870
21888
  firstMed?.src,
@@ -21872,7 +21890,8 @@ var BottlenecksContent = ({
21872
21890
  firstLowValue?.src,
21873
21891
  firstBestCycle?.src,
21874
21892
  firstWorstCycle?.src,
21875
- firstSOPDeviation?.src
21893
+ firstSOPDeviation?.src,
21894
+ firstCycleCompletion?.src
21876
21895
  ].filter(Boolean));
21877
21896
  }
21878
21897
  setAllVideos(videos);
@@ -21896,6 +21915,7 @@ var BottlenecksContent = ({
21896
21915
  if (activeFilter === "sop_deviations") return video.type === "missing_quality_check";
21897
21916
  if (activeFilter === "best_cycle_time") return video.type === "best_cycle_time";
21898
21917
  if (activeFilter === "worst_cycle_time") return video.type === "worst_cycle_time";
21918
+ if (activeFilter === "cycle_completions") return video.type === "cycle_completions";
21899
21919
  if (activeFilter === "long_cycle_time") {
21900
21920
  return video.type === "bottleneck" && video.description.toLowerCase().includes("cycle time");
21901
21921
  }
@@ -21918,6 +21938,8 @@ var BottlenecksContent = ({
21918
21938
  filtered = allVideos.filter((video) => video.type === "best_cycle_time");
21919
21939
  } else if (activeFilter === "worst_cycle_time") {
21920
21940
  filtered = allVideos.filter((video) => video.type === "worst_cycle_time");
21941
+ } else if (activeFilter === "cycle_completions") {
21942
+ filtered = allVideos.filter((video) => video.type === "cycle_completions");
21921
21943
  } else if (activeFilter === "long_cycle_time") {
21922
21944
  filtered = allVideos.filter(
21923
21945
  (video) => video.type === "bottleneck" && video.description.toLowerCase().includes("cycle time")
@@ -22212,6 +22234,7 @@ var BottlenecksContent = ({
22212
22234
  bestCycleTimes: 0,
22213
22235
  worstCycleTimes: 0,
22214
22236
  longCycleTimes: 0,
22237
+ cycleCompletions: 0,
22215
22238
  total: 0
22216
22239
  };
22217
22240
  return {
@@ -22226,6 +22249,7 @@ var BottlenecksContent = ({
22226
22249
  longCycleTimes: allVideos.filter(
22227
22250
  (video) => video.type === "bottleneck" && video.description.toLowerCase().includes("cycle time")
22228
22251
  ).length,
22252
+ cycleCompletions: allVideos.filter((video) => video.type === "cycle_completions").length,
22229
22253
  total: allVideos.length
22230
22254
  };
22231
22255
  }, [allVideos]);
@@ -22246,6 +22270,8 @@ var BottlenecksContent = ({
22246
22270
  return "Best Cycle Time";
22247
22271
  case "worst_cycle_time":
22248
22272
  return "Worst Cycle Time";
22273
+ case "cycle_completions":
22274
+ return "Cycle Completion";
22249
22275
  case "bottleneck":
22250
22276
  default:
22251
22277
  return "Bottleneck";
@@ -22281,7 +22307,7 @@ var BottlenecksContent = ({
22281
22307
  ] });
22282
22308
  }
22283
22309
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-grow p-1.5 sm:p-2 lg:p-4 h-[calc(100vh-12rem)]", children: [
22284
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-3 mb-4", children: [
22310
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-5 gap-3 mb-4", children: [
22285
22311
  /* @__PURE__ */ jsxRuntime.jsxs(
22286
22312
  Card2,
22287
22313
  {
@@ -22401,11 +22427,41 @@ var BottlenecksContent = ({
22401
22427
  ] }) })
22402
22428
  ]
22403
22429
  }
22430
+ ),
22431
+ /* @__PURE__ */ jsxRuntime.jsxs(
22432
+ Card2,
22433
+ {
22434
+ onClick: () => {
22435
+ setActiveFilter("cycle_completions");
22436
+ trackCoreEvent("Cycle Completions Filter Clicked", {
22437
+ workspaceId,
22438
+ workspaceName,
22439
+ date,
22440
+ filterType: "cycle_completions",
22441
+ clipCount: clipCounts.cycleCompletions
22442
+ });
22443
+ },
22444
+ className: `bg-white shadow-sm cursor-pointer transition-all duration-200 hover:bg-gray-50 ${activeFilter === "cycle_completions" ? "bg-blue-50 shadow-md ring-1 ring-blue-200" : ""}`,
22445
+ "aria-label": `Filter by Cycle Completions (${clipCounts.cycleCompletions} clips)`,
22446
+ role: "button",
22447
+ tabIndex: 0,
22448
+ onKeyDown: (e) => e.key === "Enter" && setActiveFilter("cycle_completions"),
22449
+ children: [
22450
+ /* @__PURE__ */ jsxRuntime.jsx(CardHeader2, { className: "pb-2", children: /* @__PURE__ */ jsxRuntime.jsx(CardTitle2, { className: `text-lg ${activeFilter === "cycle_completions" ? "text-blue-600" : ""}`, children: "Cycle Completions" }) }),
22451
+ /* @__PURE__ */ jsxRuntime.jsx(CardContent2, { children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col justify-center", children: [
22452
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-3xl font-bold text-blue-600", children: clipCounts.cycleCompletions }),
22453
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center text-sm text-gray-500 mt-1", children: [
22454
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-2 w-2 rounded-full bg-blue-600 mr-1.5" }),
22455
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: "Completed production cycles" })
22456
+ ] })
22457
+ ] }) })
22458
+ ]
22459
+ }
22404
22460
  )
22405
22461
  ] }),
22406
22462
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "bg-white rounded-lg shadow-sm overflow-hidden", style: { height: "calc(100% - 8.5rem)" }, children: [
22407
22463
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-4 py-3 border-b border-gray-100", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex justify-between items-center", children: [
22408
- /* @__PURE__ */ jsxRuntime.jsx("h3", { className: "text-lg font-semibold text-gray-800", children: activeFilter === "low_value" ? `Idle Moments (${clipCounts.lowValue})` : activeFilter === "best_cycle_time" ? `Best Cycle Time (${clipCounts.bestCycleTimes})` : activeFilter === "worst_cycle_time" ? `Worst Cycle Time (${clipCounts.worstCycleTimes})` : activeFilter === "long_cycle_time" ? `Long Cycle Time (${clipCounts.longCycleTimes})` : `All Clips (${clipCounts.total})` }),
22464
+ /* @__PURE__ */ jsxRuntime.jsx("h3", { className: "text-lg font-semibold text-gray-800", children: activeFilter === "low_value" ? `Idle Moments (${clipCounts.lowValue})` : activeFilter === "best_cycle_time" ? `Best Cycle Time (${clipCounts.bestCycleTimes})` : activeFilter === "worst_cycle_time" ? `Worst Cycle Time (${clipCounts.worstCycleTimes})` : activeFilter === "long_cycle_time" ? `Long Cycle Time (${clipCounts.longCycleTimes})` : activeFilter === "cycle_completions" ? `Cycle Completions (${clipCounts.cycleCompletions})` : `All Clips (${clipCounts.total})` }),
22409
22465
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center space-x-2", children: [
22410
22466
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative", ref: timestampFilterRef, children: [
22411
22467
  /* @__PURE__ */ jsxRuntime.jsx(
@@ -22560,9 +22616,9 @@ var BottlenecksContent = ({
22560
22616
  }
22561
22617
  )
22562
22618
  ] }) }),
22563
- (currentVideo.type === "best_cycle_time" || currentVideo.type === "worst_cycle_time" || currentVideo.type === "bottleneck" && currentVideo.description.toLowerCase().includes("cycle time")) && currentVideo.cycle_time_seconds || currentVideo.type === "low_value" ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute top-3 left-3 z-10 bg-black/60 backdrop-blur-sm px-3 py-1.5 rounded-lg text-white shadow-lg text-xs", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center", children: [
22564
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: `flex-shrink-0 h-2.5 w-2.5 rounded-full ${currentVideo.type === "low_value" ? "bg-purple-400" : currentVideo.type === "best_cycle_time" ? "bg-green-600" : currentVideo.type === "worst_cycle_time" ? "bg-red-700" : "bg-red-500"} mr-2 animate-pulse` }),
22565
- (currentVideo.type === "best_cycle_time" || currentVideo.type === "worst_cycle_time" || currentVideo.type === "bottleneck" && currentVideo.description.toLowerCase().includes("cycle time")) && currentVideo.cycle_time_seconds ? /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "opacity-90 font-mono bg-black/30 px-2 py-0.5 rounded", children: [
22619
+ (currentVideo.type === "best_cycle_time" || currentVideo.type === "worst_cycle_time" || currentVideo.type === "cycle_completions" || currentVideo.type === "bottleneck" && currentVideo.description.toLowerCase().includes("cycle time")) && currentVideo.cycle_time_seconds || currentVideo.type === "low_value" ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute top-3 left-3 z-10 bg-black/60 backdrop-blur-sm px-3 py-1.5 rounded-lg text-white shadow-lg text-xs", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center", children: [
22620
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: `flex-shrink-0 h-2.5 w-2.5 rounded-full ${currentVideo.type === "low_value" ? "bg-purple-400" : currentVideo.type === "best_cycle_time" ? "bg-green-600" : currentVideo.type === "worst_cycle_time" ? "bg-red-700" : currentVideo.type === "cycle_completions" ? "bg-blue-600" : "bg-red-500"} mr-2 animate-pulse` }),
22621
+ (currentVideo.type === "best_cycle_time" || currentVideo.type === "worst_cycle_time" || currentVideo.type === "cycle_completions" || currentVideo.type === "bottleneck" && currentVideo.description.toLowerCase().includes("cycle time")) && currentVideo.cycle_time_seconds ? /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "opacity-90 font-mono bg-black/30 px-2 py-0.5 rounded", children: [
22566
22622
  "Cycle time: ",
22567
22623
  (currentVideo.cycle_time_seconds / 20).toFixed(1),
22568
22624
  "s"
@@ -22644,9 +22700,9 @@ var BottlenecksContent = ({
22644
22700
  children: /* @__PURE__ */ jsxRuntime.jsx("svg", { xmlns: "http://www.w3.org/2000/svg", className: "h-6 w-6", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ jsxRuntime.jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M6 18L18 6M6 6l12 12" }) })
22645
22701
  }
22646
22702
  ),
22647
- (currentVideo.type === "best_cycle_time" || currentVideo.type === "worst_cycle_time" || currentVideo.type === "bottleneck" && currentVideo.description.toLowerCase().includes("cycle time")) && currentVideo.cycle_time_seconds || currentVideo.type === "low_value" ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute top-4 left-4 z-[101] bg-black/60 backdrop-blur-sm px-4 py-2 rounded-lg text-white shadow-lg text-sm", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center", children: [
22648
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: `flex-shrink-0 h-2.5 w-2.5 rounded-full ${currentVideo.type === "low_value" ? "bg-purple-400" : currentVideo.type === "best_cycle_time" ? "bg-green-600" : currentVideo.type === "worst_cycle_time" ? "bg-red-700" : "bg-red-500"} mr-2` }),
22649
- (currentVideo.type === "best_cycle_time" || currentVideo.type === "worst_cycle_time" || currentVideo.type === "bottleneck" && currentVideo.description.toLowerCase().includes("cycle time")) && currentVideo.cycle_time_seconds ? /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "opacity-90 font-mono bg-black/30 px-2 py-1 rounded", children: [
22703
+ (currentVideo.type === "best_cycle_time" || currentVideo.type === "worst_cycle_time" || currentVideo.type === "cycle_completions" || currentVideo.type === "bottleneck" && currentVideo.description.toLowerCase().includes("cycle time")) && currentVideo.cycle_time_seconds || currentVideo.type === "low_value" ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute top-4 left-4 z-[101] bg-black/60 backdrop-blur-sm px-4 py-2 rounded-lg text-white shadow-lg text-sm", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center", children: [
22704
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: `flex-shrink-0 h-2.5 w-2.5 rounded-full ${currentVideo.type === "low_value" ? "bg-purple-400" : currentVideo.type === "best_cycle_time" ? "bg-green-600" : currentVideo.type === "worst_cycle_time" ? "bg-red-700" : currentVideo.type === "cycle_completions" ? "bg-blue-600" : "bg-red-500"} mr-2` }),
22705
+ (currentVideo.type === "best_cycle_time" || currentVideo.type === "worst_cycle_time" || currentVideo.type === "cycle_completions" || currentVideo.type === "bottleneck" && currentVideo.description.toLowerCase().includes("cycle time")) && currentVideo.cycle_time_seconds ? /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "opacity-90 font-mono bg-black/30 px-2 py-1 rounded", children: [
22650
22706
  "Cycle time: ",
22651
22707
  (currentVideo.cycle_time_seconds / 20).toFixed(1),
22652
22708
  "s"
@@ -25332,6 +25388,38 @@ var AIAgentView = () => {
25332
25388
  }
25333
25389
  return null;
25334
25390
  };
25391
+ const DualAxisTooltip = ({ active, payload, label }) => {
25392
+ if (active && payload && payload.length) {
25393
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "bg-white px-4 py-3 shadow-lg rounded-lg border border-gray-200", children: [
25394
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm font-medium text-gray-900 mb-2", children: label }),
25395
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "space-y-1", children: payload.map((entry, index) => {
25396
+ const value = typeof entry.value === "number" ? formatNumber(entry.value) : entry.value;
25397
+ const unit = entry.dataKey === args.left_y_field ? args.left_unit || "" : entry.dataKey === args.right_y_field ? args.right_unit || "" : "";
25398
+ return /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-sm", style: { color: entry.color }, children: [
25399
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "font-medium", children: [
25400
+ entry.name,
25401
+ ":"
25402
+ ] }),
25403
+ " ",
25404
+ value,
25405
+ unit
25406
+ ] }, index);
25407
+ }) })
25408
+ ] });
25409
+ }
25410
+ return null;
25411
+ };
25412
+ const formatXAxisTick = (value) => {
25413
+ if (typeof value === "string") {
25414
+ if (value.match(/^\d{2}\/\d{2}\s/)) {
25415
+ return value;
25416
+ }
25417
+ if (value.length > 15) {
25418
+ return value.substring(0, 12) + "...";
25419
+ }
25420
+ }
25421
+ return value;
25422
+ };
25335
25423
  const ChartWrapper = ({ children, title }) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "my-6 bg-white rounded-xl shadow-sm border border-gray-200 p-6", children: [
25336
25424
  title && /* @__PURE__ */ jsxRuntime.jsx("h3", { className: "text-base font-semibold text-gray-900 mb-4", children: title }),
25337
25425
  children
@@ -25364,7 +25452,12 @@ var AIAgentView = () => {
25364
25452
  recharts.XAxis,
25365
25453
  {
25366
25454
  dataKey: args.x_field,
25367
- ...CHART_STYLES.axis
25455
+ ...CHART_STYLES.axis,
25456
+ angle: -45,
25457
+ textAnchor: "end",
25458
+ height: 60,
25459
+ interval: 0,
25460
+ tickFormatter: formatXAxisTick
25368
25461
  }
25369
25462
  ),
25370
25463
  /* @__PURE__ */ jsxRuntime.jsx(
@@ -25396,7 +25489,12 @@ var AIAgentView = () => {
25396
25489
  recharts.XAxis,
25397
25490
  {
25398
25491
  dataKey: args.x_field,
25399
- ...CHART_STYLES.axis
25492
+ ...CHART_STYLES.axis,
25493
+ angle: -45,
25494
+ textAnchor: "end",
25495
+ height: 60,
25496
+ interval: 0,
25497
+ tickFormatter: formatXAxisTick
25400
25498
  }
25401
25499
  ),
25402
25500
  /* @__PURE__ */ jsxRuntime.jsx(
@@ -25490,7 +25588,12 @@ var AIAgentView = () => {
25490
25588
  recharts.XAxis,
25491
25589
  {
25492
25590
  dataKey: args.x_field,
25493
- ...CHART_STYLES.axis
25591
+ ...CHART_STYLES.axis,
25592
+ angle: -45,
25593
+ textAnchor: "end",
25594
+ height: 60,
25595
+ interval: 0,
25596
+ tickFormatter: formatXAxisTick
25494
25597
  }
25495
25598
  ),
25496
25599
  /* @__PURE__ */ jsxRuntime.jsx(
@@ -25538,7 +25641,12 @@ var AIAgentView = () => {
25538
25641
  recharts.XAxis,
25539
25642
  {
25540
25643
  dataKey: args.x_field,
25541
- ...CHART_STYLES.axis
25644
+ ...CHART_STYLES.axis,
25645
+ angle: -45,
25646
+ textAnchor: "end",
25647
+ height: 60,
25648
+ interval: 0,
25649
+ tickFormatter: formatXAxisTick
25542
25650
  }
25543
25651
  ),
25544
25652
  /* @__PURE__ */ jsxRuntime.jsx(
@@ -25579,13 +25687,18 @@ var AIAgentView = () => {
25579
25687
  });
25580
25688
  return null;
25581
25689
  }
25582
- return /* @__PURE__ */ jsxRuntime.jsx(ChartWrapper, { title: args.title, children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-full h-80", children: /* @__PURE__ */ jsxRuntime.jsx(recharts.ResponsiveContainer, { width: "100%", height: "100%", children: /* @__PURE__ */ jsxRuntime.jsxs(recharts.ComposedChart, { data: args.data, margin: CHART_STYLES.margin, children: [
25690
+ return /* @__PURE__ */ jsxRuntime.jsx(ChartWrapper, { title: args.title, children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-full h-80", children: /* @__PURE__ */ jsxRuntime.jsx(recharts.ResponsiveContainer, { width: "100%", height: "100%", children: /* @__PURE__ */ jsxRuntime.jsxs(recharts.ComposedChart, { data: args.data, margin: { ...CHART_STYLES.margin, bottom: 80 }, children: [
25583
25691
  /* @__PURE__ */ jsxRuntime.jsx(recharts.CartesianGrid, { ...CHART_STYLES.grid }),
25584
25692
  /* @__PURE__ */ jsxRuntime.jsx(
25585
25693
  recharts.XAxis,
25586
25694
  {
25587
25695
  dataKey: args.x_field,
25588
- ...CHART_STYLES.axis
25696
+ ...CHART_STYLES.axis,
25697
+ angle: -45,
25698
+ textAnchor: "end",
25699
+ height: 100,
25700
+ interval: 0,
25701
+ tickFormatter: formatXAxisTick
25589
25702
  }
25590
25703
  ),
25591
25704
  /* @__PURE__ */ jsxRuntime.jsx(
@@ -25593,9 +25706,14 @@ var AIAgentView = () => {
25593
25706
  {
25594
25707
  yAxisId: "left",
25595
25708
  orientation: "left",
25596
- label: { value: args.left_label || "", angle: -90, position: "insideLeft" },
25709
+ label: {
25710
+ value: args.left_label || args.left_y_field,
25711
+ angle: -90,
25712
+ position: "insideLeft",
25713
+ style: { textAnchor: "middle", fill: "#4b5563" }
25714
+ },
25597
25715
  ...CHART_STYLES.axis,
25598
- tickFormatter: (value) => formatNumber(value)
25716
+ tickFormatter: (value) => `${formatNumber(value)}${args.left_unit || ""}`
25599
25717
  }
25600
25718
  ),
25601
25719
  /* @__PURE__ */ jsxRuntime.jsx(
@@ -25603,12 +25721,17 @@ var AIAgentView = () => {
25603
25721
  {
25604
25722
  yAxisId: "right",
25605
25723
  orientation: "right",
25606
- label: { value: args.right_label || "", angle: 90, position: "insideRight" },
25724
+ label: {
25725
+ value: args.right_label || args.right_y_field,
25726
+ angle: 90,
25727
+ position: "insideRight",
25728
+ style: { textAnchor: "middle", fill: "#4b5563" }
25729
+ },
25607
25730
  ...CHART_STYLES.axis,
25608
- tickFormatter: (value) => formatNumber(value)
25731
+ tickFormatter: (value) => `${formatNumber(value)}${args.right_unit || ""}`
25609
25732
  }
25610
25733
  ),
25611
- /* @__PURE__ */ jsxRuntime.jsx(recharts.Tooltip, { content: /* @__PURE__ */ jsxRuntime.jsx(CustomTooltip, {}), cursor: { fill: "rgba(0, 0, 0, 0.05)" } }),
25734
+ /* @__PURE__ */ jsxRuntime.jsx(recharts.Tooltip, { content: /* @__PURE__ */ jsxRuntime.jsx(DualAxisTooltip, {}), cursor: { fill: "rgba(0, 0, 0, 0.05)" } }),
25612
25735
  /* @__PURE__ */ jsxRuntime.jsx(
25613
25736
  recharts.Legend,
25614
25737
  {
@@ -25633,10 +25756,10 @@ var AIAgentView = () => {
25633
25756
  type: "monotone",
25634
25757
  dataKey: args.right_y_field,
25635
25758
  stroke: CHART_COLORS.danger,
25636
- strokeWidth: 2,
25759
+ strokeWidth: 3,
25637
25760
  name: args.right_label || args.right_y_field,
25638
- dot: { r: 4 },
25639
- activeDot: { r: 6 }
25761
+ dot: { r: 5, fill: CHART_COLORS.danger },
25762
+ activeDot: { r: 7 }
25640
25763
  }
25641
25764
  )
25642
25765
  ] }) }) }) }, `dual-axis-${key}`);
@@ -25714,13 +25837,18 @@ var AIAgentView = () => {
25714
25837
  });
25715
25838
  return null;
25716
25839
  }
25717
- return /* @__PURE__ */ jsxRuntime.jsx(ChartWrapper, { title: args.title, children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-full h-80", children: /* @__PURE__ */ jsxRuntime.jsx(recharts.ResponsiveContainer, { width: "100%", height: "100%", children: /* @__PURE__ */ jsxRuntime.jsxs(recharts.ComposedChart, { data: args.data, margin: CHART_STYLES.margin, children: [
25840
+ return /* @__PURE__ */ jsxRuntime.jsx(ChartWrapper, { title: args.title, children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-full h-80", children: /* @__PURE__ */ jsxRuntime.jsx(recharts.ResponsiveContainer, { width: "100%", height: "100%", children: /* @__PURE__ */ jsxRuntime.jsxs(recharts.ComposedChart, { data: args.data, margin: { ...CHART_STYLES.margin, bottom: 80 }, children: [
25718
25841
  /* @__PURE__ */ jsxRuntime.jsx(recharts.CartesianGrid, { ...CHART_STYLES.grid }),
25719
25842
  /* @__PURE__ */ jsxRuntime.jsx(
25720
25843
  recharts.XAxis,
25721
25844
  {
25722
25845
  dataKey: args.x_field,
25723
- ...CHART_STYLES.axis
25846
+ ...CHART_STYLES.axis,
25847
+ angle: -45,
25848
+ textAnchor: "end",
25849
+ height: 100,
25850
+ interval: 0,
25851
+ tickFormatter: formatXAxisTick
25724
25852
  }
25725
25853
  ),
25726
25854
  /* @__PURE__ */ jsxRuntime.jsx(
@@ -25766,10 +25894,10 @@ var AIAgentView = () => {
25766
25894
  type: "monotone",
25767
25895
  dataKey: args.line_field,
25768
25896
  stroke: CHART_COLORS.danger,
25769
- strokeWidth: 2,
25897
+ strokeWidth: 3,
25770
25898
  name: args.line_field,
25771
- dot: { r: 4 },
25772
- activeDot: { r: 6 }
25899
+ dot: { r: 5 },
25900
+ activeDot: { r: 7 }
25773
25901
  }
25774
25902
  )
25775
25903
  ] }) }) }) }, `combo-${key}`);
@@ -25783,7 +25911,7 @@ var AIAgentView = () => {
25783
25911
  });
25784
25912
  return null;
25785
25913
  }
25786
- return /* @__PURE__ */ jsxRuntime.jsx(ChartWrapper, { title: args.title, children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-full h-80", children: /* @__PURE__ */ jsxRuntime.jsx(recharts.ResponsiveContainer, { width: "100%", height: "100%", children: /* @__PURE__ */ jsxRuntime.jsxs(recharts.ComposedChart, { data: args.data, margin: CHART_STYLES.margin, children: [
25914
+ return /* @__PURE__ */ jsxRuntime.jsx(ChartWrapper, { title: args.title, children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-full h-80", children: /* @__PURE__ */ jsxRuntime.jsx(recharts.ResponsiveContainer, { width: "100%", height: "100%", children: /* @__PURE__ */ jsxRuntime.jsxs(recharts.ComposedChart, { data: args.data, margin: { ...CHART_STYLES.margin, bottom: 80 }, children: [
25787
25915
  /* @__PURE__ */ jsxRuntime.jsx("defs", { children: /* @__PURE__ */ jsxRuntime.jsxs("linearGradient", { id: "colorGradient", x1: "0", y1: "0", x2: "0", y2: "1", children: [
25788
25916
  /* @__PURE__ */ jsxRuntime.jsx("stop", { offset: "5%", stopColor: CHART_COLORS.primary, stopOpacity: 0.8 }),
25789
25917
  /* @__PURE__ */ jsxRuntime.jsx("stop", { offset: "95%", stopColor: CHART_COLORS.primary, stopOpacity: 0.1 })
@@ -25793,7 +25921,12 @@ var AIAgentView = () => {
25793
25921
  recharts.XAxis,
25794
25922
  {
25795
25923
  dataKey: args.x_field,
25796
- ...CHART_STYLES.axis
25924
+ ...CHART_STYLES.axis,
25925
+ angle: -45,
25926
+ textAnchor: "end",
25927
+ height: 100,
25928
+ interval: 0,
25929
+ tickFormatter: formatXAxisTick
25797
25930
  }
25798
25931
  ),
25799
25932
  /* @__PURE__ */ jsxRuntime.jsx(
@@ -25855,6 +25988,31 @@ var AIAgentView = () => {
25855
25988
  opacity: 1;
25856
25989
  }
25857
25990
  }
25991
+
25992
+ @keyframes waveLoad {
25993
+ 0% {
25994
+ background-position: -200% 0;
25995
+ }
25996
+ 100% {
25997
+ background-position: 200% 0;
25998
+ }
25999
+ }
26000
+
26001
+ .thinking-wave {
26002
+ background: linear-gradient(
26003
+ 90deg,
26004
+ #6b7280 0%,
26005
+ #6b7280 40%,
26006
+ #3b82f6 50%,
26007
+ #6b7280 60%,
26008
+ #6b7280 100%
26009
+ );
26010
+ background-size: 200% 100%;
26011
+ -webkit-background-clip: text;
26012
+ background-clip: text;
26013
+ -webkit-text-fill-color: transparent;
26014
+ animation: waveLoad 3s ease-in-out infinite;
26015
+ }
25858
26016
  `
25859
26017
  } }),
25860
26018
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `flex-1 flex flex-col h-screen transition-all duration-300 ${isSidebarOpen ? "mr-80" : "mr-0"}`, children: [
@@ -26004,14 +26162,7 @@ var AIAgentView = () => {
26004
26162
  )),
26005
26163
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex gap-4 justify-start", children: [
26006
26164
  /* @__PURE__ */ jsxRuntime.jsx(ProfilePicture, {}),
26007
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "bg-white border border-gray-200/80 px-5 py-4 rounded-2xl shadow-sm max-w-full", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3", children: [
26008
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex space-x-1", children: [
26009
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-2 h-2 bg-blue-500 rounded-full animate-bounce" }),
26010
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-2 h-2 bg-blue-500 rounded-full animate-bounce", style: { animationDelay: "0.1s" } }),
26011
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-2 h-2 bg-blue-500 rounded-full animate-bounce", style: { animationDelay: "0.2s" } })
26012
- ] }),
26013
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-gray-600 text-sm", children: "Axel is thinking..." })
26014
- ] }) })
26165
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "bg-white border border-gray-200/80 px-5 py-4 rounded-2xl shadow-sm max-w-full", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center", children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm font-medium thinking-wave", children: "Thinking" }) }) })
26015
26166
  ] })
26016
26167
  ] }) })
26017
26168
  ) : (
@@ -26077,14 +26228,7 @@ var AIAgentView = () => {
26077
26228
  ] }),
26078
26229
  isCurrentThreadLoading && !currentStreaming.message && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex gap-4 justify-start", children: [
26079
26230
  /* @__PURE__ */ jsxRuntime.jsx(ProfilePicture, {}),
26080
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "bg-white border border-gray-200/80 px-5 py-4 rounded-2xl shadow-sm max-w-full", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3", children: [
26081
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex space-x-1", children: [
26082
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-2 h-2 bg-blue-500 rounded-full animate-bounce" }),
26083
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-2 h-2 bg-blue-500 rounded-full animate-bounce", style: { animationDelay: "0.1s" } }),
26084
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-2 h-2 bg-blue-500 rounded-full animate-bounce", style: { animationDelay: "0.2s" } })
26085
- ] }),
26086
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-gray-600 text-sm", children: "Axel is thinking..." })
26087
- ] }) })
26231
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "bg-white border border-gray-200/80 px-5 py-4 rounded-2xl shadow-sm max-w-full", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center", children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm font-medium thinking-wave", children: "Thinking" }) }) })
26088
26232
  ] }),
26089
26233
  /* @__PURE__ */ jsxRuntime.jsx("div", { ref: messagesEndRef })
26090
26234
  ] }) })
package/dist/index.mjs CHANGED
@@ -1876,8 +1876,8 @@ var SSEChatClient = class {
1876
1876
  user_id: userId,
1877
1877
  context
1878
1878
  });
1879
- const agnoApiUrl = this.baseUrl || "https://optifye-agent-production.up.railway.app";
1880
- const endpoint = `${agnoApiUrl}/api/chat`;
1879
+ const agnoApiUrl = this.baseUrl || "https://fastapi-production-111f9.up.railway.app";
1880
+ const endpoint = `${agnoApiUrl}/api/v2/chat`;
1881
1881
  console.log("[SSEClient] Posting directly to AGNO:", endpoint);
1882
1882
  const response = await fetch(endpoint, {
1883
1883
  method: "POST",
@@ -1935,7 +1935,7 @@ var SSEChatClient = class {
1935
1935
  const decoder = new TextDecoder();
1936
1936
  let buffer = "";
1937
1937
  try {
1938
- console.log("[SSEClient] Starting to read stream...");
1938
+ console.log("[SSEClient] Starting to read enhanced stream...");
1939
1939
  while (true) {
1940
1940
  const { done, value } = await reader.read();
1941
1941
  if (done) {
@@ -1965,11 +1965,14 @@ var SSEChatClient = class {
1965
1965
  case "message":
1966
1966
  callbacks.onMessage?.(data.text);
1967
1967
  break;
1968
- case "reasoning":
1969
- callbacks.onReasoning?.(data.text);
1968
+ case "tool_call":
1969
+ callbacks.onToolCall?.(data.tools);
1970
+ break;
1971
+ case "tool_result":
1972
+ callbacks.onToolResult?.(data.results);
1970
1973
  break;
1971
1974
  case "complete":
1972
- callbacks.onComplete?.(data.message_id);
1975
+ callbacks.onComplete?.(data.message_id, data.metrics);
1973
1976
  break;
1974
1977
  case "error":
1975
1978
  callbacks.onError?.(data.error);
@@ -21302,6 +21305,14 @@ function parseS3Uri(s3Uri) {
21302
21305
  severity = "high";
21303
21306
  description = "Worst Cycle Time Performance";
21304
21307
  break;
21308
+ case "cycle_completions":
21309
+ case "cycle_completion":
21310
+ case "completed_cycles":
21311
+ case "completed_cycle":
21312
+ type = "cycle_completions";
21313
+ severity = "low";
21314
+ description = "Cycle Completion";
21315
+ break;
21305
21316
  case "medium_bottleneck":
21306
21317
  severity = "medium";
21307
21318
  description = "Medium Bottleneck Identified";
@@ -21328,6 +21339,10 @@ function parseS3Uri(s3Uri) {
21328
21339
  type = "bottleneck";
21329
21340
  severity = "high";
21330
21341
  description = "Long Cycle Time Detected";
21342
+ } else if (normalizedViolationType.includes("cycle") && (normalizedViolationType.includes("completion") || normalizedViolationType.includes("complete"))) {
21343
+ type = "cycle_completions";
21344
+ severity = "low";
21345
+ description = "Cycle Completion";
21331
21346
  } else {
21332
21347
  description = `Clip type: ${violationType.replace(/_/g, " ")}`;
21333
21348
  console.log(`Detected unknown violation type: ${violationType} in URI: ${s3Uri}`);
@@ -21507,7 +21522,7 @@ var S3ClipsService = class {
21507
21522
  }
21508
21523
  let cycleTimeSeconds = null;
21509
21524
  let creationTimestamp = void 0;
21510
- if (includeMetadata || includeCycleTime && (parsedInfo.type === "bottleneck" && parsedInfo.description.toLowerCase().includes("cycle time") || parsedInfo.type === "best_cycle_time" || parsedInfo.type === "worst_cycle_time")) {
21525
+ if (includeMetadata || includeCycleTime && (parsedInfo.type === "bottleneck" && parsedInfo.description.toLowerCase().includes("cycle time") || parsedInfo.type === "best_cycle_time" || parsedInfo.type === "worst_cycle_time" || parsedInfo.type === "cycle_completions")) {
21511
21526
  const metadata = await this.getFullMetadata(uri);
21512
21527
  if (metadata) {
21513
21528
  if (metadata.original_task_metadata?.cycle_time) {
@@ -21540,6 +21555,7 @@ var S3ClipsService = class {
21540
21555
  low_value: 0,
21541
21556
  long_cycle_time: 0,
21542
21557
  missing_quality_check: 0,
21558
+ cycle_completions: 0,
21543
21559
  total: 0
21544
21560
  };
21545
21561
  const samples = {
@@ -21548,7 +21564,8 @@ var S3ClipsService = class {
21548
21564
  bottleneck: null,
21549
21565
  low_value: null,
21550
21566
  long_cycle_time: null,
21551
- missing_quality_check: null
21567
+ missing_quality_check: null,
21568
+ cycle_completions: null
21552
21569
  };
21553
21570
  for (const uri of s3Uris) {
21554
21571
  const parsedInfo = parseS3Uri(uri);
@@ -21836,6 +21853,7 @@ var BottlenecksContent = ({
21836
21853
  const firstBestCycle = videos.find((v) => v.type === "best_cycle_time");
21837
21854
  const firstWorstCycle = videos.find((v) => v.type === "worst_cycle_time");
21838
21855
  const firstSOPDeviation = videos.find((v) => v.type === "missing_quality_check");
21856
+ const firstCycleCompletion = videos.find((v) => v.type === "cycle_completions");
21839
21857
  preloadVideosUrl2([
21840
21858
  firstHigh?.src,
21841
21859
  firstMed?.src,
@@ -21843,7 +21861,8 @@ var BottlenecksContent = ({
21843
21861
  firstLowValue?.src,
21844
21862
  firstBestCycle?.src,
21845
21863
  firstWorstCycle?.src,
21846
- firstSOPDeviation?.src
21864
+ firstSOPDeviation?.src,
21865
+ firstCycleCompletion?.src
21847
21866
  ].filter(Boolean));
21848
21867
  }
21849
21868
  setAllVideos(videos);
@@ -21867,6 +21886,7 @@ var BottlenecksContent = ({
21867
21886
  if (activeFilter === "sop_deviations") return video.type === "missing_quality_check";
21868
21887
  if (activeFilter === "best_cycle_time") return video.type === "best_cycle_time";
21869
21888
  if (activeFilter === "worst_cycle_time") return video.type === "worst_cycle_time";
21889
+ if (activeFilter === "cycle_completions") return video.type === "cycle_completions";
21870
21890
  if (activeFilter === "long_cycle_time") {
21871
21891
  return video.type === "bottleneck" && video.description.toLowerCase().includes("cycle time");
21872
21892
  }
@@ -21889,6 +21909,8 @@ var BottlenecksContent = ({
21889
21909
  filtered = allVideos.filter((video) => video.type === "best_cycle_time");
21890
21910
  } else if (activeFilter === "worst_cycle_time") {
21891
21911
  filtered = allVideos.filter((video) => video.type === "worst_cycle_time");
21912
+ } else if (activeFilter === "cycle_completions") {
21913
+ filtered = allVideos.filter((video) => video.type === "cycle_completions");
21892
21914
  } else if (activeFilter === "long_cycle_time") {
21893
21915
  filtered = allVideos.filter(
21894
21916
  (video) => video.type === "bottleneck" && video.description.toLowerCase().includes("cycle time")
@@ -22183,6 +22205,7 @@ var BottlenecksContent = ({
22183
22205
  bestCycleTimes: 0,
22184
22206
  worstCycleTimes: 0,
22185
22207
  longCycleTimes: 0,
22208
+ cycleCompletions: 0,
22186
22209
  total: 0
22187
22210
  };
22188
22211
  return {
@@ -22197,6 +22220,7 @@ var BottlenecksContent = ({
22197
22220
  longCycleTimes: allVideos.filter(
22198
22221
  (video) => video.type === "bottleneck" && video.description.toLowerCase().includes("cycle time")
22199
22222
  ).length,
22223
+ cycleCompletions: allVideos.filter((video) => video.type === "cycle_completions").length,
22200
22224
  total: allVideos.length
22201
22225
  };
22202
22226
  }, [allVideos]);
@@ -22217,6 +22241,8 @@ var BottlenecksContent = ({
22217
22241
  return "Best Cycle Time";
22218
22242
  case "worst_cycle_time":
22219
22243
  return "Worst Cycle Time";
22244
+ case "cycle_completions":
22245
+ return "Cycle Completion";
22220
22246
  case "bottleneck":
22221
22247
  default:
22222
22248
  return "Bottleneck";
@@ -22252,7 +22278,7 @@ var BottlenecksContent = ({
22252
22278
  ] });
22253
22279
  }
22254
22280
  return /* @__PURE__ */ jsxs("div", { className: "flex-grow p-1.5 sm:p-2 lg:p-4 h-[calc(100vh-12rem)]", children: [
22255
- /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-3 mb-4", children: [
22281
+ /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-5 gap-3 mb-4", children: [
22256
22282
  /* @__PURE__ */ jsxs(
22257
22283
  Card2,
22258
22284
  {
@@ -22372,11 +22398,41 @@ var BottlenecksContent = ({
22372
22398
  ] }) })
22373
22399
  ]
22374
22400
  }
22401
+ ),
22402
+ /* @__PURE__ */ jsxs(
22403
+ Card2,
22404
+ {
22405
+ onClick: () => {
22406
+ setActiveFilter("cycle_completions");
22407
+ trackCoreEvent("Cycle Completions Filter Clicked", {
22408
+ workspaceId,
22409
+ workspaceName,
22410
+ date,
22411
+ filterType: "cycle_completions",
22412
+ clipCount: clipCounts.cycleCompletions
22413
+ });
22414
+ },
22415
+ className: `bg-white shadow-sm cursor-pointer transition-all duration-200 hover:bg-gray-50 ${activeFilter === "cycle_completions" ? "bg-blue-50 shadow-md ring-1 ring-blue-200" : ""}`,
22416
+ "aria-label": `Filter by Cycle Completions (${clipCounts.cycleCompletions} clips)`,
22417
+ role: "button",
22418
+ tabIndex: 0,
22419
+ onKeyDown: (e) => e.key === "Enter" && setActiveFilter("cycle_completions"),
22420
+ children: [
22421
+ /* @__PURE__ */ jsx(CardHeader2, { className: "pb-2", children: /* @__PURE__ */ jsx(CardTitle2, { className: `text-lg ${activeFilter === "cycle_completions" ? "text-blue-600" : ""}`, children: "Cycle Completions" }) }),
22422
+ /* @__PURE__ */ jsx(CardContent2, { children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col justify-center", children: [
22423
+ /* @__PURE__ */ jsx("p", { className: "text-3xl font-bold text-blue-600", children: clipCounts.cycleCompletions }),
22424
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center text-sm text-gray-500 mt-1", children: [
22425
+ /* @__PURE__ */ jsx("div", { className: "h-2 w-2 rounded-full bg-blue-600 mr-1.5" }),
22426
+ /* @__PURE__ */ jsx("span", { children: "Completed production cycles" })
22427
+ ] })
22428
+ ] }) })
22429
+ ]
22430
+ }
22375
22431
  )
22376
22432
  ] }),
22377
22433
  /* @__PURE__ */ jsxs("div", { className: "bg-white rounded-lg shadow-sm overflow-hidden", style: { height: "calc(100% - 8.5rem)" }, children: [
22378
22434
  /* @__PURE__ */ jsx("div", { className: "px-4 py-3 border-b border-gray-100", children: /* @__PURE__ */ jsxs("div", { className: "flex justify-between items-center", children: [
22379
- /* @__PURE__ */ jsx("h3", { className: "text-lg font-semibold text-gray-800", children: activeFilter === "low_value" ? `Idle Moments (${clipCounts.lowValue})` : activeFilter === "best_cycle_time" ? `Best Cycle Time (${clipCounts.bestCycleTimes})` : activeFilter === "worst_cycle_time" ? `Worst Cycle Time (${clipCounts.worstCycleTimes})` : activeFilter === "long_cycle_time" ? `Long Cycle Time (${clipCounts.longCycleTimes})` : `All Clips (${clipCounts.total})` }),
22435
+ /* @__PURE__ */ jsx("h3", { className: "text-lg font-semibold text-gray-800", children: activeFilter === "low_value" ? `Idle Moments (${clipCounts.lowValue})` : activeFilter === "best_cycle_time" ? `Best Cycle Time (${clipCounts.bestCycleTimes})` : activeFilter === "worst_cycle_time" ? `Worst Cycle Time (${clipCounts.worstCycleTimes})` : activeFilter === "long_cycle_time" ? `Long Cycle Time (${clipCounts.longCycleTimes})` : activeFilter === "cycle_completions" ? `Cycle Completions (${clipCounts.cycleCompletions})` : `All Clips (${clipCounts.total})` }),
22380
22436
  /* @__PURE__ */ jsxs("div", { className: "flex items-center space-x-2", children: [
22381
22437
  /* @__PURE__ */ jsxs("div", { className: "relative", ref: timestampFilterRef, children: [
22382
22438
  /* @__PURE__ */ jsx(
@@ -22531,9 +22587,9 @@ var BottlenecksContent = ({
22531
22587
  }
22532
22588
  )
22533
22589
  ] }) }),
22534
- (currentVideo.type === "best_cycle_time" || currentVideo.type === "worst_cycle_time" || currentVideo.type === "bottleneck" && currentVideo.description.toLowerCase().includes("cycle time")) && currentVideo.cycle_time_seconds || currentVideo.type === "low_value" ? /* @__PURE__ */ jsx("div", { className: "absolute top-3 left-3 z-10 bg-black/60 backdrop-blur-sm px-3 py-1.5 rounded-lg text-white shadow-lg text-xs", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center", children: [
22535
- /* @__PURE__ */ jsx("div", { className: `flex-shrink-0 h-2.5 w-2.5 rounded-full ${currentVideo.type === "low_value" ? "bg-purple-400" : currentVideo.type === "best_cycle_time" ? "bg-green-600" : currentVideo.type === "worst_cycle_time" ? "bg-red-700" : "bg-red-500"} mr-2 animate-pulse` }),
22536
- (currentVideo.type === "best_cycle_time" || currentVideo.type === "worst_cycle_time" || currentVideo.type === "bottleneck" && currentVideo.description.toLowerCase().includes("cycle time")) && currentVideo.cycle_time_seconds ? /* @__PURE__ */ jsxs("span", { className: "opacity-90 font-mono bg-black/30 px-2 py-0.5 rounded", children: [
22590
+ (currentVideo.type === "best_cycle_time" || currentVideo.type === "worst_cycle_time" || currentVideo.type === "cycle_completions" || currentVideo.type === "bottleneck" && currentVideo.description.toLowerCase().includes("cycle time")) && currentVideo.cycle_time_seconds || currentVideo.type === "low_value" ? /* @__PURE__ */ jsx("div", { className: "absolute top-3 left-3 z-10 bg-black/60 backdrop-blur-sm px-3 py-1.5 rounded-lg text-white shadow-lg text-xs", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center", children: [
22591
+ /* @__PURE__ */ jsx("div", { className: `flex-shrink-0 h-2.5 w-2.5 rounded-full ${currentVideo.type === "low_value" ? "bg-purple-400" : currentVideo.type === "best_cycle_time" ? "bg-green-600" : currentVideo.type === "worst_cycle_time" ? "bg-red-700" : currentVideo.type === "cycle_completions" ? "bg-blue-600" : "bg-red-500"} mr-2 animate-pulse` }),
22592
+ (currentVideo.type === "best_cycle_time" || currentVideo.type === "worst_cycle_time" || currentVideo.type === "cycle_completions" || currentVideo.type === "bottleneck" && currentVideo.description.toLowerCase().includes("cycle time")) && currentVideo.cycle_time_seconds ? /* @__PURE__ */ jsxs("span", { className: "opacity-90 font-mono bg-black/30 px-2 py-0.5 rounded", children: [
22537
22593
  "Cycle time: ",
22538
22594
  (currentVideo.cycle_time_seconds / 20).toFixed(1),
22539
22595
  "s"
@@ -22615,9 +22671,9 @@ var BottlenecksContent = ({
22615
22671
  children: /* @__PURE__ */ jsx("svg", { xmlns: "http://www.w3.org/2000/svg", className: "h-6 w-6", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M6 18L18 6M6 6l12 12" }) })
22616
22672
  }
22617
22673
  ),
22618
- (currentVideo.type === "best_cycle_time" || currentVideo.type === "worst_cycle_time" || currentVideo.type === "bottleneck" && currentVideo.description.toLowerCase().includes("cycle time")) && currentVideo.cycle_time_seconds || currentVideo.type === "low_value" ? /* @__PURE__ */ jsx("div", { className: "absolute top-4 left-4 z-[101] bg-black/60 backdrop-blur-sm px-4 py-2 rounded-lg text-white shadow-lg text-sm", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center", children: [
22619
- /* @__PURE__ */ jsx("div", { className: `flex-shrink-0 h-2.5 w-2.5 rounded-full ${currentVideo.type === "low_value" ? "bg-purple-400" : currentVideo.type === "best_cycle_time" ? "bg-green-600" : currentVideo.type === "worst_cycle_time" ? "bg-red-700" : "bg-red-500"} mr-2` }),
22620
- (currentVideo.type === "best_cycle_time" || currentVideo.type === "worst_cycle_time" || currentVideo.type === "bottleneck" && currentVideo.description.toLowerCase().includes("cycle time")) && currentVideo.cycle_time_seconds ? /* @__PURE__ */ jsxs("span", { className: "opacity-90 font-mono bg-black/30 px-2 py-1 rounded", children: [
22674
+ (currentVideo.type === "best_cycle_time" || currentVideo.type === "worst_cycle_time" || currentVideo.type === "cycle_completions" || currentVideo.type === "bottleneck" && currentVideo.description.toLowerCase().includes("cycle time")) && currentVideo.cycle_time_seconds || currentVideo.type === "low_value" ? /* @__PURE__ */ jsx("div", { className: "absolute top-4 left-4 z-[101] bg-black/60 backdrop-blur-sm px-4 py-2 rounded-lg text-white shadow-lg text-sm", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center", children: [
22675
+ /* @__PURE__ */ jsx("div", { className: `flex-shrink-0 h-2.5 w-2.5 rounded-full ${currentVideo.type === "low_value" ? "bg-purple-400" : currentVideo.type === "best_cycle_time" ? "bg-green-600" : currentVideo.type === "worst_cycle_time" ? "bg-red-700" : currentVideo.type === "cycle_completions" ? "bg-blue-600" : "bg-red-500"} mr-2` }),
22676
+ (currentVideo.type === "best_cycle_time" || currentVideo.type === "worst_cycle_time" || currentVideo.type === "cycle_completions" || currentVideo.type === "bottleneck" && currentVideo.description.toLowerCase().includes("cycle time")) && currentVideo.cycle_time_seconds ? /* @__PURE__ */ jsxs("span", { className: "opacity-90 font-mono bg-black/30 px-2 py-1 rounded", children: [
22621
22677
  "Cycle time: ",
22622
22678
  (currentVideo.cycle_time_seconds / 20).toFixed(1),
22623
22679
  "s"
@@ -25303,6 +25359,38 @@ var AIAgentView = () => {
25303
25359
  }
25304
25360
  return null;
25305
25361
  };
25362
+ const DualAxisTooltip = ({ active, payload, label }) => {
25363
+ if (active && payload && payload.length) {
25364
+ return /* @__PURE__ */ jsxs("div", { className: "bg-white px-4 py-3 shadow-lg rounded-lg border border-gray-200", children: [
25365
+ /* @__PURE__ */ jsx("p", { className: "text-sm font-medium text-gray-900 mb-2", children: label }),
25366
+ /* @__PURE__ */ jsx("div", { className: "space-y-1", children: payload.map((entry, index) => {
25367
+ const value = typeof entry.value === "number" ? formatNumber(entry.value) : entry.value;
25368
+ const unit = entry.dataKey === args.left_y_field ? args.left_unit || "" : entry.dataKey === args.right_y_field ? args.right_unit || "" : "";
25369
+ return /* @__PURE__ */ jsxs("p", { className: "text-sm", style: { color: entry.color }, children: [
25370
+ /* @__PURE__ */ jsxs("span", { className: "font-medium", children: [
25371
+ entry.name,
25372
+ ":"
25373
+ ] }),
25374
+ " ",
25375
+ value,
25376
+ unit
25377
+ ] }, index);
25378
+ }) })
25379
+ ] });
25380
+ }
25381
+ return null;
25382
+ };
25383
+ const formatXAxisTick = (value) => {
25384
+ if (typeof value === "string") {
25385
+ if (value.match(/^\d{2}\/\d{2}\s/)) {
25386
+ return value;
25387
+ }
25388
+ if (value.length > 15) {
25389
+ return value.substring(0, 12) + "...";
25390
+ }
25391
+ }
25392
+ return value;
25393
+ };
25306
25394
  const ChartWrapper = ({ children, title }) => /* @__PURE__ */ jsxs("div", { className: "my-6 bg-white rounded-xl shadow-sm border border-gray-200 p-6", children: [
25307
25395
  title && /* @__PURE__ */ jsx("h3", { className: "text-base font-semibold text-gray-900 mb-4", children: title }),
25308
25396
  children
@@ -25335,7 +25423,12 @@ var AIAgentView = () => {
25335
25423
  XAxis,
25336
25424
  {
25337
25425
  dataKey: args.x_field,
25338
- ...CHART_STYLES.axis
25426
+ ...CHART_STYLES.axis,
25427
+ angle: -45,
25428
+ textAnchor: "end",
25429
+ height: 60,
25430
+ interval: 0,
25431
+ tickFormatter: formatXAxisTick
25339
25432
  }
25340
25433
  ),
25341
25434
  /* @__PURE__ */ jsx(
@@ -25367,7 +25460,12 @@ var AIAgentView = () => {
25367
25460
  XAxis,
25368
25461
  {
25369
25462
  dataKey: args.x_field,
25370
- ...CHART_STYLES.axis
25463
+ ...CHART_STYLES.axis,
25464
+ angle: -45,
25465
+ textAnchor: "end",
25466
+ height: 60,
25467
+ interval: 0,
25468
+ tickFormatter: formatXAxisTick
25371
25469
  }
25372
25470
  ),
25373
25471
  /* @__PURE__ */ jsx(
@@ -25461,7 +25559,12 @@ var AIAgentView = () => {
25461
25559
  XAxis,
25462
25560
  {
25463
25561
  dataKey: args.x_field,
25464
- ...CHART_STYLES.axis
25562
+ ...CHART_STYLES.axis,
25563
+ angle: -45,
25564
+ textAnchor: "end",
25565
+ height: 60,
25566
+ interval: 0,
25567
+ tickFormatter: formatXAxisTick
25465
25568
  }
25466
25569
  ),
25467
25570
  /* @__PURE__ */ jsx(
@@ -25509,7 +25612,12 @@ var AIAgentView = () => {
25509
25612
  XAxis,
25510
25613
  {
25511
25614
  dataKey: args.x_field,
25512
- ...CHART_STYLES.axis
25615
+ ...CHART_STYLES.axis,
25616
+ angle: -45,
25617
+ textAnchor: "end",
25618
+ height: 60,
25619
+ interval: 0,
25620
+ tickFormatter: formatXAxisTick
25513
25621
  }
25514
25622
  ),
25515
25623
  /* @__PURE__ */ jsx(
@@ -25550,13 +25658,18 @@ var AIAgentView = () => {
25550
25658
  });
25551
25659
  return null;
25552
25660
  }
25553
- return /* @__PURE__ */ jsx(ChartWrapper, { title: args.title, children: /* @__PURE__ */ jsx("div", { className: "w-full h-80", children: /* @__PURE__ */ jsx(ResponsiveContainer, { width: "100%", height: "100%", children: /* @__PURE__ */ jsxs(ComposedChart, { data: args.data, margin: CHART_STYLES.margin, children: [
25661
+ return /* @__PURE__ */ jsx(ChartWrapper, { title: args.title, children: /* @__PURE__ */ jsx("div", { className: "w-full h-80", children: /* @__PURE__ */ jsx(ResponsiveContainer, { width: "100%", height: "100%", children: /* @__PURE__ */ jsxs(ComposedChart, { data: args.data, margin: { ...CHART_STYLES.margin, bottom: 80 }, children: [
25554
25662
  /* @__PURE__ */ jsx(CartesianGrid, { ...CHART_STYLES.grid }),
25555
25663
  /* @__PURE__ */ jsx(
25556
25664
  XAxis,
25557
25665
  {
25558
25666
  dataKey: args.x_field,
25559
- ...CHART_STYLES.axis
25667
+ ...CHART_STYLES.axis,
25668
+ angle: -45,
25669
+ textAnchor: "end",
25670
+ height: 100,
25671
+ interval: 0,
25672
+ tickFormatter: formatXAxisTick
25560
25673
  }
25561
25674
  ),
25562
25675
  /* @__PURE__ */ jsx(
@@ -25564,9 +25677,14 @@ var AIAgentView = () => {
25564
25677
  {
25565
25678
  yAxisId: "left",
25566
25679
  orientation: "left",
25567
- label: { value: args.left_label || "", angle: -90, position: "insideLeft" },
25680
+ label: {
25681
+ value: args.left_label || args.left_y_field,
25682
+ angle: -90,
25683
+ position: "insideLeft",
25684
+ style: { textAnchor: "middle", fill: "#4b5563" }
25685
+ },
25568
25686
  ...CHART_STYLES.axis,
25569
- tickFormatter: (value) => formatNumber(value)
25687
+ tickFormatter: (value) => `${formatNumber(value)}${args.left_unit || ""}`
25570
25688
  }
25571
25689
  ),
25572
25690
  /* @__PURE__ */ jsx(
@@ -25574,12 +25692,17 @@ var AIAgentView = () => {
25574
25692
  {
25575
25693
  yAxisId: "right",
25576
25694
  orientation: "right",
25577
- label: { value: args.right_label || "", angle: 90, position: "insideRight" },
25695
+ label: {
25696
+ value: args.right_label || args.right_y_field,
25697
+ angle: 90,
25698
+ position: "insideRight",
25699
+ style: { textAnchor: "middle", fill: "#4b5563" }
25700
+ },
25578
25701
  ...CHART_STYLES.axis,
25579
- tickFormatter: (value) => formatNumber(value)
25702
+ tickFormatter: (value) => `${formatNumber(value)}${args.right_unit || ""}`
25580
25703
  }
25581
25704
  ),
25582
- /* @__PURE__ */ jsx(Tooltip, { content: /* @__PURE__ */ jsx(CustomTooltip, {}), cursor: { fill: "rgba(0, 0, 0, 0.05)" } }),
25705
+ /* @__PURE__ */ jsx(Tooltip, { content: /* @__PURE__ */ jsx(DualAxisTooltip, {}), cursor: { fill: "rgba(0, 0, 0, 0.05)" } }),
25583
25706
  /* @__PURE__ */ jsx(
25584
25707
  Legend,
25585
25708
  {
@@ -25604,10 +25727,10 @@ var AIAgentView = () => {
25604
25727
  type: "monotone",
25605
25728
  dataKey: args.right_y_field,
25606
25729
  stroke: CHART_COLORS.danger,
25607
- strokeWidth: 2,
25730
+ strokeWidth: 3,
25608
25731
  name: args.right_label || args.right_y_field,
25609
- dot: { r: 4 },
25610
- activeDot: { r: 6 }
25732
+ dot: { r: 5, fill: CHART_COLORS.danger },
25733
+ activeDot: { r: 7 }
25611
25734
  }
25612
25735
  )
25613
25736
  ] }) }) }) }, `dual-axis-${key}`);
@@ -25685,13 +25808,18 @@ var AIAgentView = () => {
25685
25808
  });
25686
25809
  return null;
25687
25810
  }
25688
- return /* @__PURE__ */ jsx(ChartWrapper, { title: args.title, children: /* @__PURE__ */ jsx("div", { className: "w-full h-80", children: /* @__PURE__ */ jsx(ResponsiveContainer, { width: "100%", height: "100%", children: /* @__PURE__ */ jsxs(ComposedChart, { data: args.data, margin: CHART_STYLES.margin, children: [
25811
+ return /* @__PURE__ */ jsx(ChartWrapper, { title: args.title, children: /* @__PURE__ */ jsx("div", { className: "w-full h-80", children: /* @__PURE__ */ jsx(ResponsiveContainer, { width: "100%", height: "100%", children: /* @__PURE__ */ jsxs(ComposedChart, { data: args.data, margin: { ...CHART_STYLES.margin, bottom: 80 }, children: [
25689
25812
  /* @__PURE__ */ jsx(CartesianGrid, { ...CHART_STYLES.grid }),
25690
25813
  /* @__PURE__ */ jsx(
25691
25814
  XAxis,
25692
25815
  {
25693
25816
  dataKey: args.x_field,
25694
- ...CHART_STYLES.axis
25817
+ ...CHART_STYLES.axis,
25818
+ angle: -45,
25819
+ textAnchor: "end",
25820
+ height: 100,
25821
+ interval: 0,
25822
+ tickFormatter: formatXAxisTick
25695
25823
  }
25696
25824
  ),
25697
25825
  /* @__PURE__ */ jsx(
@@ -25737,10 +25865,10 @@ var AIAgentView = () => {
25737
25865
  type: "monotone",
25738
25866
  dataKey: args.line_field,
25739
25867
  stroke: CHART_COLORS.danger,
25740
- strokeWidth: 2,
25868
+ strokeWidth: 3,
25741
25869
  name: args.line_field,
25742
- dot: { r: 4 },
25743
- activeDot: { r: 6 }
25870
+ dot: { r: 5 },
25871
+ activeDot: { r: 7 }
25744
25872
  }
25745
25873
  )
25746
25874
  ] }) }) }) }, `combo-${key}`);
@@ -25754,7 +25882,7 @@ var AIAgentView = () => {
25754
25882
  });
25755
25883
  return null;
25756
25884
  }
25757
- return /* @__PURE__ */ jsx(ChartWrapper, { title: args.title, children: /* @__PURE__ */ jsx("div", { className: "w-full h-80", children: /* @__PURE__ */ jsx(ResponsiveContainer, { width: "100%", height: "100%", children: /* @__PURE__ */ jsxs(ComposedChart, { data: args.data, margin: CHART_STYLES.margin, children: [
25885
+ return /* @__PURE__ */ jsx(ChartWrapper, { title: args.title, children: /* @__PURE__ */ jsx("div", { className: "w-full h-80", children: /* @__PURE__ */ jsx(ResponsiveContainer, { width: "100%", height: "100%", children: /* @__PURE__ */ jsxs(ComposedChart, { data: args.data, margin: { ...CHART_STYLES.margin, bottom: 80 }, children: [
25758
25886
  /* @__PURE__ */ jsx("defs", { children: /* @__PURE__ */ jsxs("linearGradient", { id: "colorGradient", x1: "0", y1: "0", x2: "0", y2: "1", children: [
25759
25887
  /* @__PURE__ */ jsx("stop", { offset: "5%", stopColor: CHART_COLORS.primary, stopOpacity: 0.8 }),
25760
25888
  /* @__PURE__ */ jsx("stop", { offset: "95%", stopColor: CHART_COLORS.primary, stopOpacity: 0.1 })
@@ -25764,7 +25892,12 @@ var AIAgentView = () => {
25764
25892
  XAxis,
25765
25893
  {
25766
25894
  dataKey: args.x_field,
25767
- ...CHART_STYLES.axis
25895
+ ...CHART_STYLES.axis,
25896
+ angle: -45,
25897
+ textAnchor: "end",
25898
+ height: 100,
25899
+ interval: 0,
25900
+ tickFormatter: formatXAxisTick
25768
25901
  }
25769
25902
  ),
25770
25903
  /* @__PURE__ */ jsx(
@@ -25826,6 +25959,31 @@ var AIAgentView = () => {
25826
25959
  opacity: 1;
25827
25960
  }
25828
25961
  }
25962
+
25963
+ @keyframes waveLoad {
25964
+ 0% {
25965
+ background-position: -200% 0;
25966
+ }
25967
+ 100% {
25968
+ background-position: 200% 0;
25969
+ }
25970
+ }
25971
+
25972
+ .thinking-wave {
25973
+ background: linear-gradient(
25974
+ 90deg,
25975
+ #6b7280 0%,
25976
+ #6b7280 40%,
25977
+ #3b82f6 50%,
25978
+ #6b7280 60%,
25979
+ #6b7280 100%
25980
+ );
25981
+ background-size: 200% 100%;
25982
+ -webkit-background-clip: text;
25983
+ background-clip: text;
25984
+ -webkit-text-fill-color: transparent;
25985
+ animation: waveLoad 3s ease-in-out infinite;
25986
+ }
25829
25987
  `
25830
25988
  } }),
25831
25989
  /* @__PURE__ */ jsxs("div", { className: `flex-1 flex flex-col h-screen transition-all duration-300 ${isSidebarOpen ? "mr-80" : "mr-0"}`, children: [
@@ -25975,14 +26133,7 @@ var AIAgentView = () => {
25975
26133
  )),
25976
26134
  /* @__PURE__ */ jsxs("div", { className: "flex gap-4 justify-start", children: [
25977
26135
  /* @__PURE__ */ jsx(ProfilePicture, {}),
25978
- /* @__PURE__ */ jsx("div", { className: "bg-white border border-gray-200/80 px-5 py-4 rounded-2xl shadow-sm max-w-full", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3", children: [
25979
- /* @__PURE__ */ jsxs("div", { className: "flex space-x-1", children: [
25980
- /* @__PURE__ */ jsx("div", { className: "w-2 h-2 bg-blue-500 rounded-full animate-bounce" }),
25981
- /* @__PURE__ */ jsx("div", { className: "w-2 h-2 bg-blue-500 rounded-full animate-bounce", style: { animationDelay: "0.1s" } }),
25982
- /* @__PURE__ */ jsx("div", { className: "w-2 h-2 bg-blue-500 rounded-full animate-bounce", style: { animationDelay: "0.2s" } })
25983
- ] }),
25984
- /* @__PURE__ */ jsx("span", { className: "text-gray-600 text-sm", children: "Axel is thinking..." })
25985
- ] }) })
26136
+ /* @__PURE__ */ jsx("div", { className: "bg-white border border-gray-200/80 px-5 py-4 rounded-2xl shadow-sm max-w-full", children: /* @__PURE__ */ jsx("div", { className: "flex items-center", children: /* @__PURE__ */ jsx("span", { className: "text-sm font-medium thinking-wave", children: "Thinking" }) }) })
25986
26137
  ] })
25987
26138
  ] }) })
25988
26139
  ) : (
@@ -26048,14 +26199,7 @@ var AIAgentView = () => {
26048
26199
  ] }),
26049
26200
  isCurrentThreadLoading && !currentStreaming.message && /* @__PURE__ */ jsxs("div", { className: "flex gap-4 justify-start", children: [
26050
26201
  /* @__PURE__ */ jsx(ProfilePicture, {}),
26051
- /* @__PURE__ */ jsx("div", { className: "bg-white border border-gray-200/80 px-5 py-4 rounded-2xl shadow-sm max-w-full", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3", children: [
26052
- /* @__PURE__ */ jsxs("div", { className: "flex space-x-1", children: [
26053
- /* @__PURE__ */ jsx("div", { className: "w-2 h-2 bg-blue-500 rounded-full animate-bounce" }),
26054
- /* @__PURE__ */ jsx("div", { className: "w-2 h-2 bg-blue-500 rounded-full animate-bounce", style: { animationDelay: "0.1s" } }),
26055
- /* @__PURE__ */ jsx("div", { className: "w-2 h-2 bg-blue-500 rounded-full animate-bounce", style: { animationDelay: "0.2s" } })
26056
- ] }),
26057
- /* @__PURE__ */ jsx("span", { className: "text-gray-600 text-sm", children: "Axel is thinking..." })
26058
- ] }) })
26202
+ /* @__PURE__ */ jsx("div", { className: "bg-white border border-gray-200/80 px-5 py-4 rounded-2xl shadow-sm max-w-full", children: /* @__PURE__ */ jsx("div", { className: "flex items-center", children: /* @__PURE__ */ jsx("span", { className: "text-sm font-medium thinking-wave", children: "Thinking" }) }) })
26059
26203
  ] }),
26060
26204
  /* @__PURE__ */ jsx("div", { ref: messagesEndRef })
26061
26205
  ] }) })
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@optifye/dashboard-core",
3
- "version": "4.3.6",
3
+ "version": "4.3.9",
4
4
  "description": "Reusable UI & logic for Optifye dashboard",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",