@optifye/dashboard-core 4.0.1 → 4.1.0
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 +124 -1
- package/dist/index.d.ts +124 -1
- package/dist/index.js +1054 -402
- package/dist/index.mjs +1045 -403
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -6,19 +6,19 @@ import { subDays, format, parseISO, isValid, isFuture, isToday } from 'date-fns'
|
|
|
6
6
|
import { toZonedTime, formatInTimeZone } from 'date-fns-tz';
|
|
7
7
|
import { REALTIME_SUBSCRIBE_STATES, createClient } from '@supabase/supabase-js';
|
|
8
8
|
import mixpanel from 'mixpanel-browser';
|
|
9
|
+
import useSWR from 'swr';
|
|
9
10
|
import Hls2 from 'hls.js';
|
|
10
11
|
import { noop, warning, invariant, progress, secondsToMilliseconds, millisecondsToSeconds, memo as memo$1 } from 'motion-utils';
|
|
11
12
|
import { getValueTransition, hover, press, isPrimaryPointer, GroupPlaybackControls, setDragLock, supportsLinearEasing, attachTimeline, isGenerator, calcGeneratorDuration, isWaapiSupportedEasing, mapEasingToNativeEasing, maxGeneratorDuration, generateLinearEasing, isBezierDefinition } from 'motion-dom';
|
|
12
13
|
import { ResponsiveContainer, BarChart as BarChart$1, CartesianGrid, XAxis, YAxis, Tooltip, ReferenceLine, Bar, Cell, LabelList, PieChart, Pie, Legend, LineChart as LineChart$1, Line } from 'recharts';
|
|
13
14
|
import { Slot } from '@radix-ui/react-slot';
|
|
14
|
-
import { Camera, Map as Map$1, Video, ChevronDown, ChevronUp, Check, X, Clock, Coffee, Plus, Minus, ArrowDown, ArrowUp, Search, CheckCircle, AlertTriangle, Info, Share2, Download, User, XCircle, ChevronLeft, ChevronRight, AlertCircle, Sun, Moon, ArrowLeft, Copy, RefreshCw,
|
|
15
|
+
import { Camera, Map as Map$1, Video, ChevronDown, ChevronUp, Check, X, Clock, Coffee, Plus, Minus, ArrowDown, ArrowUp, Search, CheckCircle, AlertTriangle, Info, Share2, Download, User, XCircle, ChevronLeft, ChevronRight, AlertCircle, Sun, Moon, MessageSquare, Trash2, Menu, ArrowLeft, Copy, RefreshCw, Send, Edit2, UserCheck, Save, LogOut, Calendar, Clock8, AlarmClock, Settings, LifeBuoy, Loader2, ArrowLeftIcon as ArrowLeftIcon$1, Settings2, CheckCircle2, Zap, UserCircle } from 'lucide-react';
|
|
15
16
|
import { DayPicker, useNavigation as useNavigation$1 } from 'react-day-picker';
|
|
16
17
|
import html2canvas from 'html2canvas';
|
|
17
18
|
import jsPDF, { jsPDF as jsPDF$1 } from 'jspdf';
|
|
18
19
|
import { S3Client, ListObjectsV2Command, GetObjectCommand } from '@aws-sdk/client-s3';
|
|
19
20
|
import { HomeIcon, TrophyIcon, ChartBarIcon, AdjustmentsHorizontalIcon, ClockIcon, SparklesIcon, UserCircleIcon, ArrowRightIcon, ExclamationCircleIcon, InformationCircleIcon, ArrowLeftIcon, ChevronLeftIcon, ChevronRightIcon } from '@heroicons/react/24/outline';
|
|
20
21
|
import * as SelectPrimitive from '@radix-ui/react-select';
|
|
21
|
-
import useSWR from 'swr';
|
|
22
22
|
import { toast } from 'sonner';
|
|
23
23
|
import { getSignedUrl } from '@aws-sdk/s3-request-presigner';
|
|
24
24
|
import { Readable } from 'stream';
|
|
@@ -5612,7 +5612,9 @@ var DEFAULT_DATE_TIME_CONFIG = {
|
|
|
5612
5612
|
}
|
|
5613
5613
|
};
|
|
5614
5614
|
var DEFAULT_ENDPOINTS_CONFIG = {
|
|
5615
|
-
whatsapp: "/api/send-whatsapp-direct"
|
|
5615
|
+
whatsapp: "/api/send-whatsapp-direct",
|
|
5616
|
+
agnoApiUrl: process.env.NEXT_PUBLIC_AGNO_URL || "https://optifye-agent-production.up.railway.app"
|
|
5617
|
+
// Default AGNO API URL
|
|
5616
5618
|
};
|
|
5617
5619
|
var DEFAULT_THEME_CONFIG = {
|
|
5618
5620
|
// Sensible defaults for theme can be added here
|
|
@@ -8206,6 +8208,210 @@ var resetCoreMixpanel = () => {
|
|
|
8206
8208
|
mixpanel.reset();
|
|
8207
8209
|
};
|
|
8208
8210
|
|
|
8211
|
+
// src/lib/services/sseClient.ts
|
|
8212
|
+
var SSEChatClient = class {
|
|
8213
|
+
constructor(baseUrl) {
|
|
8214
|
+
this.controllers = /* @__PURE__ */ new Map();
|
|
8215
|
+
this.baseUrl = baseUrl || "";
|
|
8216
|
+
}
|
|
8217
|
+
async sendMessage(message, userId, threadId, context, callbacks) {
|
|
8218
|
+
const connectionId = `${threadId || "new"}-${Date.now()}`;
|
|
8219
|
+
if (threadId) {
|
|
8220
|
+
for (const [id3, controller2] of this.controllers.entries()) {
|
|
8221
|
+
if (id3.startsWith(threadId)) {
|
|
8222
|
+
controller2.abort();
|
|
8223
|
+
this.controllers.delete(id3);
|
|
8224
|
+
}
|
|
8225
|
+
}
|
|
8226
|
+
}
|
|
8227
|
+
const controller = new AbortController();
|
|
8228
|
+
this.controllers.set(connectionId, controller);
|
|
8229
|
+
console.log("[SSEClient] Sending message:", {
|
|
8230
|
+
message,
|
|
8231
|
+
thread_id: threadId,
|
|
8232
|
+
user_id: userId,
|
|
8233
|
+
context
|
|
8234
|
+
});
|
|
8235
|
+
const agnoApiUrl = this.baseUrl || "https://optifye-agent-production.up.railway.app";
|
|
8236
|
+
const endpoint = `${agnoApiUrl}/api/chat`;
|
|
8237
|
+
console.log("[SSEClient] Posting directly to AGNO:", endpoint);
|
|
8238
|
+
const response = await fetch(endpoint, {
|
|
8239
|
+
method: "POST",
|
|
8240
|
+
headers: {
|
|
8241
|
+
"Content-Type": "application/json",
|
|
8242
|
+
"Accept": "text/event-stream"
|
|
8243
|
+
},
|
|
8244
|
+
body: JSON.stringify({
|
|
8245
|
+
message,
|
|
8246
|
+
thread_id: threadId,
|
|
8247
|
+
user_id: userId,
|
|
8248
|
+
company_id: context.companyId,
|
|
8249
|
+
line_id: context.lineId,
|
|
8250
|
+
shift_id: context.shiftId
|
|
8251
|
+
}),
|
|
8252
|
+
signal: controller.signal,
|
|
8253
|
+
// Don't include credentials since the API returns Access-Control-Allow-Origin: *
|
|
8254
|
+
// credentials: 'include', // Include cookies for CORS
|
|
8255
|
+
mode: "cors"
|
|
8256
|
+
// Explicitly set CORS mode
|
|
8257
|
+
});
|
|
8258
|
+
console.log("[SSEClient] Response status:", response.status);
|
|
8259
|
+
console.log("[SSEClient] Response headers:", Object.fromEntries(response.headers.entries()));
|
|
8260
|
+
if (!response.ok) {
|
|
8261
|
+
let errorMessage = `Chat request failed with status ${response.status}`;
|
|
8262
|
+
try {
|
|
8263
|
+
const error = await response.json();
|
|
8264
|
+
errorMessage = error.detail || error.message || errorMessage;
|
|
8265
|
+
} catch (e) {
|
|
8266
|
+
try {
|
|
8267
|
+
const text = await response.text();
|
|
8268
|
+
if (text) errorMessage = text;
|
|
8269
|
+
} catch (textError) {
|
|
8270
|
+
}
|
|
8271
|
+
}
|
|
8272
|
+
console.error("[SSEClient] Error response:", errorMessage);
|
|
8273
|
+
throw new Error(errorMessage);
|
|
8274
|
+
}
|
|
8275
|
+
const contentType = response.headers.get("content-type");
|
|
8276
|
+
if (!contentType?.includes("text/event-stream")) {
|
|
8277
|
+
console.warn("[SSEClient] Unexpected content-type:", contentType);
|
|
8278
|
+
}
|
|
8279
|
+
try {
|
|
8280
|
+
await this.handleSSEStream(response, callbacks);
|
|
8281
|
+
} finally {
|
|
8282
|
+
this.controllers.delete(connectionId);
|
|
8283
|
+
}
|
|
8284
|
+
}
|
|
8285
|
+
async handleSSEStream(response, callbacks) {
|
|
8286
|
+
if (!response.body) {
|
|
8287
|
+
console.error("[SSEClient] Response body is null");
|
|
8288
|
+
throw new Error("No response body available for streaming");
|
|
8289
|
+
}
|
|
8290
|
+
const reader = response.body.getReader();
|
|
8291
|
+
const decoder = new TextDecoder();
|
|
8292
|
+
let buffer = "";
|
|
8293
|
+
try {
|
|
8294
|
+
console.log("[SSEClient] Starting to read stream...");
|
|
8295
|
+
while (true) {
|
|
8296
|
+
const { done, value } = await reader.read();
|
|
8297
|
+
if (done) {
|
|
8298
|
+
console.log("[SSEClient] Stream ended");
|
|
8299
|
+
break;
|
|
8300
|
+
}
|
|
8301
|
+
buffer += decoder.decode(value, { stream: true });
|
|
8302
|
+
const lines = buffer.split("\n");
|
|
8303
|
+
buffer = lines.pop() || "";
|
|
8304
|
+
for (let i = 0; i < lines.length; i++) {
|
|
8305
|
+
const line = lines[i].trim();
|
|
8306
|
+
if (!line) continue;
|
|
8307
|
+
console.log("[SSEClient] Processing line:", line);
|
|
8308
|
+
if (line.startsWith("event:")) {
|
|
8309
|
+
const event = line.slice(6).trim();
|
|
8310
|
+
console.log("[SSEClient] Event type:", event);
|
|
8311
|
+
const nextLine = lines[i + 1];
|
|
8312
|
+
if (nextLine?.startsWith("data:")) {
|
|
8313
|
+
const dataStr = nextLine.slice(5).trim();
|
|
8314
|
+
console.log("[SSEClient] Event data:", dataStr);
|
|
8315
|
+
try {
|
|
8316
|
+
const data = JSON.parse(dataStr);
|
|
8317
|
+
switch (event) {
|
|
8318
|
+
case "thread":
|
|
8319
|
+
callbacks.onThreadCreated?.(data.thread_id);
|
|
8320
|
+
break;
|
|
8321
|
+
case "message":
|
|
8322
|
+
callbacks.onMessage?.(data.text);
|
|
8323
|
+
break;
|
|
8324
|
+
case "reasoning":
|
|
8325
|
+
callbacks.onReasoning?.(data.text);
|
|
8326
|
+
break;
|
|
8327
|
+
case "complete":
|
|
8328
|
+
callbacks.onComplete?.(data.message_id);
|
|
8329
|
+
break;
|
|
8330
|
+
case "error":
|
|
8331
|
+
callbacks.onError?.(data.error);
|
|
8332
|
+
break;
|
|
8333
|
+
}
|
|
8334
|
+
} catch (e) {
|
|
8335
|
+
console.error("[SSEClient] Failed to parse data:", dataStr, e);
|
|
8336
|
+
}
|
|
8337
|
+
i++;
|
|
8338
|
+
}
|
|
8339
|
+
}
|
|
8340
|
+
}
|
|
8341
|
+
}
|
|
8342
|
+
} finally {
|
|
8343
|
+
reader.releaseLock();
|
|
8344
|
+
}
|
|
8345
|
+
}
|
|
8346
|
+
abort(threadId) {
|
|
8347
|
+
if (threadId) {
|
|
8348
|
+
for (const [id3, controller] of this.controllers.entries()) {
|
|
8349
|
+
if (id3.startsWith(threadId)) {
|
|
8350
|
+
controller.abort();
|
|
8351
|
+
this.controllers.delete(id3);
|
|
8352
|
+
}
|
|
8353
|
+
}
|
|
8354
|
+
} else {
|
|
8355
|
+
for (const [id3, controller] of this.controllers.entries()) {
|
|
8356
|
+
controller.abort();
|
|
8357
|
+
}
|
|
8358
|
+
this.controllers.clear();
|
|
8359
|
+
}
|
|
8360
|
+
}
|
|
8361
|
+
};
|
|
8362
|
+
|
|
8363
|
+
// src/lib/services/chatService.ts
|
|
8364
|
+
async function getUserThreads(userId, limit = 20) {
|
|
8365
|
+
const supabase = _getSupabaseInstance();
|
|
8366
|
+
const { data, error } = await supabase.schema("ai").from("chat_threads").select("*").eq("user_id", userId).order("updated_at", { ascending: false }).limit(limit);
|
|
8367
|
+
if (error) throw error;
|
|
8368
|
+
return data;
|
|
8369
|
+
}
|
|
8370
|
+
async function getUserThreadsPaginated(userId, page = 1, pageSize = 20) {
|
|
8371
|
+
const supabase = _getSupabaseInstance();
|
|
8372
|
+
const from = (page - 1) * pageSize;
|
|
8373
|
+
const to = from + pageSize - 1;
|
|
8374
|
+
const { data, error, count } = await supabase.schema("ai").from("chat_threads").select("*", { count: "exact" }).eq("user_id", userId).order("updated_at", { ascending: false }).range(from, to);
|
|
8375
|
+
if (error) throw error;
|
|
8376
|
+
return {
|
|
8377
|
+
threads: data,
|
|
8378
|
+
totalCount: count || 0,
|
|
8379
|
+
totalPages: Math.ceil((count || 0) / pageSize),
|
|
8380
|
+
currentPage: page
|
|
8381
|
+
};
|
|
8382
|
+
}
|
|
8383
|
+
async function getThreadMessages(threadId, limit = 50, beforePosition) {
|
|
8384
|
+
const supabase = _getSupabaseInstance();
|
|
8385
|
+
let query = supabase.schema("ai").from("chat_messages").select("*").eq("thread_id", threadId).order("position", { ascending: true });
|
|
8386
|
+
if (beforePosition !== void 0) {
|
|
8387
|
+
query = query.lt("position", beforePosition);
|
|
8388
|
+
}
|
|
8389
|
+
const { data, error } = await query.limit(limit);
|
|
8390
|
+
if (error) throw error;
|
|
8391
|
+
return data;
|
|
8392
|
+
}
|
|
8393
|
+
async function getAllThreadMessages(threadId) {
|
|
8394
|
+
const supabase = _getSupabaseInstance();
|
|
8395
|
+
const { data, error } = await supabase.schema("ai").from("chat_messages").select("*").eq("thread_id", threadId).order("position", { ascending: true });
|
|
8396
|
+
if (error) throw error;
|
|
8397
|
+
return data;
|
|
8398
|
+
}
|
|
8399
|
+
async function updateThreadTitle(threadId, newTitle) {
|
|
8400
|
+
const supabase = _getSupabaseInstance();
|
|
8401
|
+
const { data, error } = await supabase.schema("ai").from("chat_threads").update({
|
|
8402
|
+
title: newTitle,
|
|
8403
|
+
auto_title: false,
|
|
8404
|
+
updated_at: (/* @__PURE__ */ new Date()).toISOString()
|
|
8405
|
+
}).eq("id", threadId).select().single();
|
|
8406
|
+
if (error) throw error;
|
|
8407
|
+
return data;
|
|
8408
|
+
}
|
|
8409
|
+
async function deleteThread(threadId) {
|
|
8410
|
+
const supabase = _getSupabaseInstance();
|
|
8411
|
+
const { error } = await supabase.schema("ai").from("chat_threads").delete().eq("id", threadId);
|
|
8412
|
+
if (error) throw error;
|
|
8413
|
+
}
|
|
8414
|
+
|
|
8209
8415
|
// src/lib/hooks/useLineDetailedMetrics.ts
|
|
8210
8416
|
var useLineDetailedMetrics = (lineIdFromProp) => {
|
|
8211
8417
|
const entityConfig = useEntityConfig();
|
|
@@ -9326,6 +9532,122 @@ var useWorkspaceOperators = (workspaceId, options) => {
|
|
|
9326
9532
|
refetch: fetchData
|
|
9327
9533
|
};
|
|
9328
9534
|
};
|
|
9535
|
+
function useThreads() {
|
|
9536
|
+
const supabase = _getSupabaseInstance();
|
|
9537
|
+
const fetcher = async (key) => {
|
|
9538
|
+
const { data: { session } } = await supabase.auth.getSession();
|
|
9539
|
+
if (!session) {
|
|
9540
|
+
console.log("[useThreads] No session found");
|
|
9541
|
+
return [];
|
|
9542
|
+
}
|
|
9543
|
+
const user = session.user;
|
|
9544
|
+
if (!user) {
|
|
9545
|
+
console.log("[useThreads] No user in session");
|
|
9546
|
+
return [];
|
|
9547
|
+
}
|
|
9548
|
+
console.log("[useThreads] Fetching threads for user:", user.id);
|
|
9549
|
+
try {
|
|
9550
|
+
const { data, error: error2 } = await supabase.schema("ai").from("chat_threads").select("*").eq("user_id", user.id).order("updated_at", { ascending: false });
|
|
9551
|
+
if (error2) {
|
|
9552
|
+
console.error("[useThreads] Error fetching threads:", error2);
|
|
9553
|
+
throw error2;
|
|
9554
|
+
}
|
|
9555
|
+
console.log("[useThreads] Fetched threads:", data?.length || 0);
|
|
9556
|
+
return data || [];
|
|
9557
|
+
} catch (err) {
|
|
9558
|
+
console.error("[useThreads] Unexpected error:", err);
|
|
9559
|
+
throw err;
|
|
9560
|
+
}
|
|
9561
|
+
};
|
|
9562
|
+
const { data: threads = [], error, isLoading, mutate } = useSWR("chat_threads", fetcher, {
|
|
9563
|
+
revalidateOnFocus: false,
|
|
9564
|
+
revalidateOnReconnect: true
|
|
9565
|
+
});
|
|
9566
|
+
const createThread = useCallback(async (title) => {
|
|
9567
|
+
const { data: { session } } = await supabase.auth.getSession();
|
|
9568
|
+
if (!session?.user) throw new Error("Not authenticated");
|
|
9569
|
+
const user = session.user;
|
|
9570
|
+
console.log("[useThreads] Creating thread for user:", user.id);
|
|
9571
|
+
const { data, error: error2 } = await supabase.schema("ai").from("chat_threads").insert([{
|
|
9572
|
+
user_id: user.id,
|
|
9573
|
+
title: title || `Chat ${(/* @__PURE__ */ new Date()).toLocaleDateString()}`,
|
|
9574
|
+
auto_title: !title,
|
|
9575
|
+
model_id: "gpt-4o-mini",
|
|
9576
|
+
has_reasoning: false,
|
|
9577
|
+
last_message: null,
|
|
9578
|
+
message_count: 0
|
|
9579
|
+
}]).select().single();
|
|
9580
|
+
if (error2) {
|
|
9581
|
+
console.error("[useThreads] Error creating thread:", error2);
|
|
9582
|
+
throw error2;
|
|
9583
|
+
}
|
|
9584
|
+
console.log("[useThreads] Created thread:", data?.id);
|
|
9585
|
+
mutate([data, ...threads], false);
|
|
9586
|
+
return data;
|
|
9587
|
+
}, [supabase, threads, mutate]);
|
|
9588
|
+
const deleteThread2 = useCallback(async (threadId) => {
|
|
9589
|
+
const { error: error2 } = await supabase.schema("ai").from("chat_threads").delete().eq("id", threadId);
|
|
9590
|
+
if (error2) throw error2;
|
|
9591
|
+
mutate(threads.filter((t) => t.id !== threadId), false);
|
|
9592
|
+
}, [supabase, threads, mutate]);
|
|
9593
|
+
return {
|
|
9594
|
+
threads,
|
|
9595
|
+
isLoading,
|
|
9596
|
+
error,
|
|
9597
|
+
mutate,
|
|
9598
|
+
createThread,
|
|
9599
|
+
deleteThread: deleteThread2
|
|
9600
|
+
};
|
|
9601
|
+
}
|
|
9602
|
+
function useMessages(threadId) {
|
|
9603
|
+
const supabase = _getSupabaseInstance();
|
|
9604
|
+
const [messages, setMessages] = useState([]);
|
|
9605
|
+
const [isLoading, setIsLoading] = useState(true);
|
|
9606
|
+
const [error, setError] = useState(null);
|
|
9607
|
+
useEffect(() => {
|
|
9608
|
+
if (!threadId) {
|
|
9609
|
+
setMessages([]);
|
|
9610
|
+
setIsLoading(false);
|
|
9611
|
+
return;
|
|
9612
|
+
}
|
|
9613
|
+
const loadMessages = async () => {
|
|
9614
|
+
setIsLoading(true);
|
|
9615
|
+
setError(null);
|
|
9616
|
+
try {
|
|
9617
|
+
const { data, error: fetchError } = await supabase.schema("ai").from("chat_messages").select("*").eq("thread_id", threadId).order("position", { ascending: true });
|
|
9618
|
+
if (fetchError) throw fetchError;
|
|
9619
|
+
setMessages(data);
|
|
9620
|
+
} catch (err) {
|
|
9621
|
+
setError(err);
|
|
9622
|
+
console.error("Error loading messages:", err);
|
|
9623
|
+
} finally {
|
|
9624
|
+
setIsLoading(false);
|
|
9625
|
+
}
|
|
9626
|
+
};
|
|
9627
|
+
loadMessages();
|
|
9628
|
+
}, [threadId, supabase]);
|
|
9629
|
+
const addMessage = useCallback(async (message) => {
|
|
9630
|
+
const maxPosition = messages.reduce((max, msg) => Math.max(max, msg.position), -1);
|
|
9631
|
+
const { data, error: insertError } = await supabase.schema("ai").from("chat_messages").insert([{
|
|
9632
|
+
...message,
|
|
9633
|
+
position: maxPosition + 1
|
|
9634
|
+
}]).select().single();
|
|
9635
|
+
if (insertError) throw insertError;
|
|
9636
|
+
return data;
|
|
9637
|
+
}, [supabase, messages]);
|
|
9638
|
+
const updateMessage = useCallback(async (id3, content) => {
|
|
9639
|
+
const { error: updateError } = await supabase.schema("ai").from("chat_messages").update({ content }).eq("id", id3);
|
|
9640
|
+
if (updateError) throw updateError;
|
|
9641
|
+
}, [supabase]);
|
|
9642
|
+
return {
|
|
9643
|
+
messages,
|
|
9644
|
+
setMessages,
|
|
9645
|
+
isLoading,
|
|
9646
|
+
error,
|
|
9647
|
+
addMessage,
|
|
9648
|
+
updateMessage
|
|
9649
|
+
};
|
|
9650
|
+
}
|
|
9329
9651
|
var DEFAULT_FACTORY_OVERVIEW_TABLE_NAME = "factory_daily_summary";
|
|
9330
9652
|
var useFactoryOverviewMetrics = (options) => {
|
|
9331
9653
|
const { companyId, factoryId: entityFactoryId } = useEntityConfig();
|
|
@@ -13037,6 +13359,15 @@ var createSupabaseClient = (url, key) => createClient(url, key, {
|
|
|
13037
13359
|
persistSession: true,
|
|
13038
13360
|
detectSessionInUrl: true,
|
|
13039
13361
|
flowType: "pkce"
|
|
13362
|
+
},
|
|
13363
|
+
db: {
|
|
13364
|
+
schema: "public"
|
|
13365
|
+
// Default schema, we'll use .schema('ai') in queries
|
|
13366
|
+
},
|
|
13367
|
+
global: {
|
|
13368
|
+
headers: {
|
|
13369
|
+
"x-application-name": "optifye-dashboard"
|
|
13370
|
+
}
|
|
13040
13371
|
}
|
|
13041
13372
|
});
|
|
13042
13373
|
var getAnonClient = () => {
|
|
@@ -21653,6 +21984,22 @@ var HourlyOutputChart = ({
|
|
|
21653
21984
|
// Keep original data for labels
|
|
21654
21985
|
color: (animatedData[i] || 0) >= Math.round(pphThreshold) ? "#00AB45" : "#E34329"
|
|
21655
21986
|
}));
|
|
21987
|
+
const maxYValue = Math.ceil(pphThreshold * 1.5);
|
|
21988
|
+
const generateYAxisTicks = () => {
|
|
21989
|
+
const targetValue = Math.round(pphThreshold);
|
|
21990
|
+
const ticks = [0];
|
|
21991
|
+
if (targetValue > 0) {
|
|
21992
|
+
ticks.push(targetValue);
|
|
21993
|
+
}
|
|
21994
|
+
const step = Math.ceil((maxYValue - targetValue) / 2);
|
|
21995
|
+
if (step > 5) {
|
|
21996
|
+
for (let i = targetValue + step; i < maxYValue; i += step) {
|
|
21997
|
+
ticks.push(i);
|
|
21998
|
+
}
|
|
21999
|
+
}
|
|
22000
|
+
ticks.push(maxYValue);
|
|
22001
|
+
return [...new Set(ticks)].sort((a, b) => a - b);
|
|
22002
|
+
};
|
|
21656
22003
|
const renderLegend = () => /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center text-sm text-gray-600 absolute -bottom-1 left-0 right-0 bg-white py-1", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 border border-gray-100 rounded-full px-3 py-1", children: [
|
|
21657
22004
|
/* @__PURE__ */ jsx("div", { className: "w-8 flex items-center", children: /* @__PURE__ */ jsx("div", { className: "w-full border-t-2 border-[#E34329] border-dashed" }) }),
|
|
21658
22005
|
/* @__PURE__ */ jsxs("span", { children: [
|
|
@@ -21692,7 +22039,8 @@ var HourlyOutputChart = ({
|
|
|
21692
22039
|
{
|
|
21693
22040
|
tickMargin: 8,
|
|
21694
22041
|
width: 35,
|
|
21695
|
-
|
|
22042
|
+
domain: [0, maxYValue],
|
|
22043
|
+
ticks: generateYAxisTicks(),
|
|
21696
22044
|
tickFormatter: (value) => value,
|
|
21697
22045
|
tick: (props) => {
|
|
21698
22046
|
const { x, y, payload } = props;
|
|
@@ -24967,9 +25315,6 @@ var S3ClipsService = class {
|
|
|
24967
25315
|
s3UriToCloudfront(s3Uri) {
|
|
24968
25316
|
const url = new URL(s3Uri);
|
|
24969
25317
|
const key = url.pathname.startsWith("/") ? url.pathname.substring(1) : url.pathname;
|
|
24970
|
-
if (typeof window !== "undefined" && window.location.hostname === "localhost") {
|
|
24971
|
-
return `/api/stream/${key}`;
|
|
24972
|
-
}
|
|
24973
25318
|
return `${this.config.s3Config.cloudFrontDomain}/${key}`;
|
|
24974
25319
|
}
|
|
24975
25320
|
/**
|
|
@@ -25783,8 +26128,7 @@ var BottlenecksContent = ({
|
|
|
25783
26128
|
loop: false,
|
|
25784
26129
|
preload: "metadata",
|
|
25785
26130
|
onClick: togglePlayback,
|
|
25786
|
-
onDoubleClick: toggleFullscreen
|
|
25787
|
-
crossOrigin: "anonymous"
|
|
26131
|
+
onDoubleClick: toggleFullscreen
|
|
25788
26132
|
},
|
|
25789
26133
|
currentVideo.id
|
|
25790
26134
|
),
|
|
@@ -28290,146 +28634,124 @@ var SingleVideoStream = ({
|
|
|
28290
28634
|
);
|
|
28291
28635
|
};
|
|
28292
28636
|
var SingleVideoStream_default = SingleVideoStream;
|
|
28293
|
-
|
|
28294
|
-
|
|
28295
|
-
|
|
28296
|
-
|
|
28297
|
-
|
|
28298
|
-
|
|
28299
|
-
}
|
|
28300
|
-
|
|
28301
|
-
|
|
28302
|
-
|
|
28303
|
-
|
|
28304
|
-
|
|
28305
|
-
const requestData = {
|
|
28306
|
-
prompt: userQuestion,
|
|
28307
|
-
line_id: lineId,
|
|
28308
|
-
shift_id: shiftId,
|
|
28309
|
-
company_id: companyId
|
|
28310
|
-
};
|
|
28311
|
-
if (context) {
|
|
28312
|
-
requestData.context = context;
|
|
28313
|
-
}
|
|
28314
|
-
console.log("[OptifyeAgent] Sending request:", requestData);
|
|
28315
|
-
const response = await fetch(`${this.apiUrl}/api/custom-analysis`, {
|
|
28316
|
-
method: "POST",
|
|
28317
|
-
headers: {
|
|
28318
|
-
"Content-Type": "application/json"
|
|
28319
|
-
},
|
|
28320
|
-
body: JSON.stringify(requestData),
|
|
28321
|
-
signal: AbortSignal.timeout(6e4)
|
|
28322
|
-
// 60 second timeout
|
|
28323
|
-
});
|
|
28324
|
-
const responseText = await response.text();
|
|
28325
|
-
console.log("[OptifyeAgent] Response status:", response.status);
|
|
28326
|
-
console.log("[OptifyeAgent] Response text:", responseText);
|
|
28327
|
-
let result;
|
|
28637
|
+
var ThreadSidebar = ({
|
|
28638
|
+
activeThreadId,
|
|
28639
|
+
onSelectThread,
|
|
28640
|
+
onNewThread,
|
|
28641
|
+
className = ""
|
|
28642
|
+
}) => {
|
|
28643
|
+
const { threads, isLoading, error, deleteThread: deleteThread2 } = useThreads();
|
|
28644
|
+
const [deletingId, setDeletingId] = useState(null);
|
|
28645
|
+
const handleDelete = async (e, threadId) => {
|
|
28646
|
+
e.stopPropagation();
|
|
28647
|
+
if (confirm("Are you sure you want to delete this conversation?")) {
|
|
28648
|
+
setDeletingId(threadId);
|
|
28328
28649
|
try {
|
|
28329
|
-
|
|
28330
|
-
|
|
28331
|
-
|
|
28332
|
-
if (responseText.includes("'Agent' object has no attribute")) {
|
|
28333
|
-
return {
|
|
28334
|
-
success: false,
|
|
28335
|
-
error: "Server error: The AI agent service is experiencing issues. Please try again later or contact support."
|
|
28336
|
-
};
|
|
28650
|
+
await deleteThread2(threadId);
|
|
28651
|
+
if (activeThreadId === threadId) {
|
|
28652
|
+
onNewThread();
|
|
28337
28653
|
}
|
|
28338
|
-
|
|
28339
|
-
|
|
28340
|
-
|
|
28341
|
-
|
|
28342
|
-
|
|
28343
|
-
if (response.ok) {
|
|
28344
|
-
return {
|
|
28345
|
-
success: result.success ?? true,
|
|
28346
|
-
analysis: result.analysis || result.response || result.message || result.data,
|
|
28347
|
-
timestamp: result.timestamp,
|
|
28348
|
-
error: result.error
|
|
28349
|
-
};
|
|
28350
|
-
} else {
|
|
28351
|
-
const errorMsg = result.error || result.message || `API request failed: ${response.status}`;
|
|
28352
|
-
console.error("[OptifyeAgent] API error:", errorMsg);
|
|
28353
|
-
if (errorMsg.includes("'Agent' object has no attribute")) {
|
|
28354
|
-
return {
|
|
28355
|
-
success: false,
|
|
28356
|
-
error: "The AI service is currently being updated. Please try again in a few moments."
|
|
28357
|
-
};
|
|
28358
|
-
}
|
|
28359
|
-
return {
|
|
28360
|
-
success: false,
|
|
28361
|
-
error: errorMsg
|
|
28362
|
-
};
|
|
28363
|
-
}
|
|
28364
|
-
} catch (error) {
|
|
28365
|
-
const errorMsg = error instanceof Error ? `Failed to connect to Optifye Agent: ${error.message}` : "Failed to connect to Optifye Agent";
|
|
28366
|
-
console.error("[OptifyeAgent] Request failed:", error);
|
|
28367
|
-
if (error instanceof Error && error.name === "AbortError") {
|
|
28368
|
-
return {
|
|
28369
|
-
success: false,
|
|
28370
|
-
error: "Request timed out. The AI agent is taking too long to respond. Please try again."
|
|
28371
|
-
};
|
|
28654
|
+
} catch (error2) {
|
|
28655
|
+
console.error("Error deleting thread:", error2);
|
|
28656
|
+
alert("Failed to delete conversation. Please try again.");
|
|
28657
|
+
} finally {
|
|
28658
|
+
setDeletingId(null);
|
|
28372
28659
|
}
|
|
28373
|
-
return {
|
|
28374
|
-
success: false,
|
|
28375
|
-
error: errorMsg
|
|
28376
|
-
};
|
|
28377
28660
|
}
|
|
28378
|
-
}
|
|
28379
|
-
|
|
28380
|
-
|
|
28381
|
-
|
|
28382
|
-
|
|
28383
|
-
|
|
28384
|
-
|
|
28385
|
-
|
|
28386
|
-
|
|
28387
|
-
|
|
28388
|
-
|
|
28389
|
-
|
|
28390
|
-
|
|
28391
|
-
}
|
|
28392
|
-
return false;
|
|
28393
|
-
} catch (error) {
|
|
28394
|
-
console.error("[OptifyeAgent] Health check failed:", error);
|
|
28395
|
-
return false;
|
|
28661
|
+
};
|
|
28662
|
+
const formatDate = (dateString) => {
|
|
28663
|
+
const date = new Date(dateString);
|
|
28664
|
+
const now2 = /* @__PURE__ */ new Date();
|
|
28665
|
+
const diffMs = now2.getTime() - date.getTime();
|
|
28666
|
+
const diffDays = Math.floor(diffMs / (1e3 * 60 * 60 * 24));
|
|
28667
|
+
if (diffDays === 0) {
|
|
28668
|
+
return "Today";
|
|
28669
|
+
} else if (diffDays === 1) {
|
|
28670
|
+
return "Yesterday";
|
|
28671
|
+
} else if (diffDays < 7) {
|
|
28672
|
+
return date.toLocaleDateString("en-US", { weekday: "short" });
|
|
28673
|
+
} else {
|
|
28674
|
+
return date.toLocaleDateString("en-US", { month: "short", day: "numeric" });
|
|
28396
28675
|
}
|
|
28676
|
+
};
|
|
28677
|
+
if (error) {
|
|
28678
|
+
return /* @__PURE__ */ jsx("div", { className: `p-4 text-red-600 text-sm ${className}`, children: "Failed to load conversations" });
|
|
28397
28679
|
}
|
|
28680
|
+
return /* @__PURE__ */ jsxs("div", { className: `flex flex-col h-full bg-gray-50 border-r border-gray-200 ${className}`, children: [
|
|
28681
|
+
/* @__PURE__ */ jsx("div", { className: "flex-shrink-0 p-4 border-b border-gray-200", children: /* @__PURE__ */ jsxs(
|
|
28682
|
+
"button",
|
|
28683
|
+
{
|
|
28684
|
+
onClick: onNewThread,
|
|
28685
|
+
className: "w-full flex items-center justify-center gap-2 px-4 py-2.5 bg-blue-600 text-white rounded-lg hover:bg-blue-700 transition-colors text-sm font-medium",
|
|
28686
|
+
children: [
|
|
28687
|
+
/* @__PURE__ */ jsx(Plus, { className: "w-4 h-4" }),
|
|
28688
|
+
"New Chat"
|
|
28689
|
+
]
|
|
28690
|
+
}
|
|
28691
|
+
) }),
|
|
28692
|
+
/* @__PURE__ */ jsx("div", { className: "flex-1 overflow-y-auto", children: isLoading ? /* @__PURE__ */ jsx("div", { className: "flex justify-center p-8", children: /* @__PURE__ */ jsx(LoadingSpinner_default, { size: "sm" }) }) : threads.length === 0 ? /* @__PURE__ */ jsx("div", { className: "p-4 text-center text-gray-500 text-sm", children: "No conversations yet" }) : /* @__PURE__ */ jsx("div", { className: "py-2", children: threads.map((thread) => /* @__PURE__ */ jsxs(
|
|
28693
|
+
"div",
|
|
28694
|
+
{
|
|
28695
|
+
onClick: () => onSelectThread(thread.id),
|
|
28696
|
+
className: `group relative flex items-start gap-3 px-4 py-3 hover:bg-gray-100 cursor-pointer transition-colors ${activeThreadId === thread.id ? "bg-gray-100" : ""}`,
|
|
28697
|
+
children: [
|
|
28698
|
+
/* @__PURE__ */ jsx(MessageSquare, { className: "w-4 h-4 text-gray-400 mt-0.5 flex-shrink-0" }),
|
|
28699
|
+
/* @__PURE__ */ jsxs("div", { className: "flex-1 min-w-0", children: [
|
|
28700
|
+
/* @__PURE__ */ jsx("h3", { className: "text-sm font-medium text-gray-900 truncate", children: thread.title || "Untitled Chat" }),
|
|
28701
|
+
/* @__PURE__ */ jsx("p", { className: "text-xs text-gray-500 mt-0.5", children: formatDate(thread.created_at) })
|
|
28702
|
+
] }),
|
|
28703
|
+
deletingId === thread.id ? /* @__PURE__ */ jsx(LoadingSpinner_default, { size: "sm", className: "flex-shrink-0" }) : /* @__PURE__ */ jsx(
|
|
28704
|
+
"button",
|
|
28705
|
+
{
|
|
28706
|
+
onClick: (e) => handleDelete(e, thread.id),
|
|
28707
|
+
className: "flex-shrink-0 opacity-0 group-hover:opacity-100 p-1 hover:bg-gray-200 rounded transition-all",
|
|
28708
|
+
title: "Delete conversation",
|
|
28709
|
+
children: /* @__PURE__ */ jsx(Trash2, { className: "w-3.5 h-3.5 text-gray-500" })
|
|
28710
|
+
}
|
|
28711
|
+
)
|
|
28712
|
+
]
|
|
28713
|
+
},
|
|
28714
|
+
thread.id
|
|
28715
|
+
)) }) }),
|
|
28716
|
+
/* @__PURE__ */ jsx("div", { className: "flex-shrink-0 p-4 border-t border-gray-200", children: /* @__PURE__ */ jsxs("p", { className: "text-xs text-gray-500 text-center", children: [
|
|
28717
|
+
threads.length,
|
|
28718
|
+
" conversation",
|
|
28719
|
+
threads.length !== 1 ? "s" : ""
|
|
28720
|
+
] }) })
|
|
28721
|
+
] });
|
|
28398
28722
|
};
|
|
28399
|
-
var optifyeAgentClient = new OptifyeAgentClient();
|
|
28400
|
-
async function getManufacturingInsights(userQuestion, lineId, shiftId, companyId, context) {
|
|
28401
|
-
if (!userQuestion || !userQuestion.trim()) {
|
|
28402
|
-
return {
|
|
28403
|
-
success: false,
|
|
28404
|
-
error: "Please provide a question"
|
|
28405
|
-
};
|
|
28406
|
-
}
|
|
28407
|
-
if (!lineId || !companyId) {
|
|
28408
|
-
console.warn("[OptifyeAgent] Missing required IDs:", { lineId, companyId });
|
|
28409
|
-
}
|
|
28410
|
-
return optifyeAgentClient.getManufacturingInsights(
|
|
28411
|
-
userQuestion,
|
|
28412
|
-
lineId,
|
|
28413
|
-
shiftId,
|
|
28414
|
-
companyId,
|
|
28415
|
-
context
|
|
28416
|
-
);
|
|
28417
|
-
}
|
|
28418
28723
|
var axelProfilePng = "/axel-profile.png";
|
|
28419
28724
|
var AIAgentView = () => {
|
|
28420
28725
|
const { navigate, pathname } = useNavigation();
|
|
28726
|
+
const config = useDashboardConfig();
|
|
28421
28727
|
const entityConfig = useEntityConfig();
|
|
28422
28728
|
const dateTimeConfig = useDateTimeConfig();
|
|
28423
28729
|
const shiftConfig = useShiftConfig();
|
|
28424
28730
|
const [inputValue, setInputValue] = useState("");
|
|
28425
|
-
const [
|
|
28426
|
-
const [isLoading, setIsLoading] = useState(false);
|
|
28731
|
+
const [loadingThreads, setLoadingThreads] = useState(/* @__PURE__ */ new Set());
|
|
28427
28732
|
const [lastError, setLastError] = useState(null);
|
|
28428
28733
|
const [copiedMessageId, setCopiedMessageId] = useState(null);
|
|
28429
|
-
const [
|
|
28734
|
+
const [activeThreadId, setActiveThreadId] = useState(void 0);
|
|
28735
|
+
const [isSidebarOpen, setIsSidebarOpen] = useState(true);
|
|
28736
|
+
const [streamingStates, setStreamingStates] = useState(/* @__PURE__ */ new Map());
|
|
28737
|
+
const [userId, setUserId] = useState(null);
|
|
28738
|
+
const [pendingThreadId, setPendingThreadId] = useState(null);
|
|
28739
|
+
const isThreadLoading = (threadId) => {
|
|
28740
|
+
return threadId ? loadingThreads.has(threadId) : false;
|
|
28741
|
+
};
|
|
28742
|
+
const getStreamingState = (threadId) => {
|
|
28743
|
+
return threadId ? streamingStates.get(threadId) || { message: "", reasoning: "" } : { message: "", reasoning: "" };
|
|
28744
|
+
};
|
|
28430
28745
|
const textareaRef = useRef(null);
|
|
28431
28746
|
const messagesEndRef = useRef(null);
|
|
28432
28747
|
const containerRef = useRef(null);
|
|
28748
|
+
const { createThread, mutate: mutateThreads } = useThreads();
|
|
28749
|
+
const { messages, addMessage, setMessages } = useMessages(activeThreadId);
|
|
28750
|
+
const agnoApiUrl = config.endpoints?.agnoApiUrl || "https://optifye-agent-production.up.railway.app";
|
|
28751
|
+
const sseClient = useMemo(() => {
|
|
28752
|
+
console.log("[AIAgentView] Using AGNO API URL:", agnoApiUrl);
|
|
28753
|
+
return new SSEChatClient(agnoApiUrl);
|
|
28754
|
+
}, [agnoApiUrl]);
|
|
28433
28755
|
const getLineIdFromPath = () => {
|
|
28434
28756
|
const pathParts = pathname.split("/");
|
|
28435
28757
|
const lineIdIndex = pathParts.findIndex((part) => part === "ai-agent") + 1;
|
|
@@ -28447,11 +28769,14 @@ var AIAgentView = () => {
|
|
|
28447
28769
|
textareaRef.current.style.height = `${Math.min(textareaRef.current.scrollHeight, 120)}px`;
|
|
28448
28770
|
}
|
|
28449
28771
|
}, [inputValue]);
|
|
28772
|
+
const scrollToBottom = () => {
|
|
28773
|
+
messagesEndRef.current?.scrollIntoView({ behavior: "smooth" });
|
|
28774
|
+
};
|
|
28450
28775
|
useEffect(() => {
|
|
28451
|
-
if (
|
|
28452
|
-
|
|
28776
|
+
if (activeThreadId && messages.length > 0) {
|
|
28777
|
+
setTimeout(scrollToBottom, 100);
|
|
28453
28778
|
}
|
|
28454
|
-
}, []);
|
|
28779
|
+
}, [activeThreadId]);
|
|
28455
28780
|
const copyToClipboard = async (text, messageId) => {
|
|
28456
28781
|
try {
|
|
28457
28782
|
await navigator.clipboard.writeText(text);
|
|
@@ -28461,101 +28786,179 @@ var AIAgentView = () => {
|
|
|
28461
28786
|
console.error("Failed to copy text: ", err);
|
|
28462
28787
|
}
|
|
28463
28788
|
};
|
|
28789
|
+
const handleNewThread = () => {
|
|
28790
|
+
setActiveThreadId(void 0);
|
|
28791
|
+
setMessages([]);
|
|
28792
|
+
setInputValue("");
|
|
28793
|
+
setPendingThreadId(null);
|
|
28794
|
+
textareaRef.current?.focus();
|
|
28795
|
+
};
|
|
28796
|
+
useEffect(() => {
|
|
28797
|
+
const checkAuth = async () => {
|
|
28798
|
+
const supabase2 = _getSupabaseInstance();
|
|
28799
|
+
const { data: { session } } = await supabase2.auth.getSession();
|
|
28800
|
+
if (session?.user) {
|
|
28801
|
+
setUserId(session.user.id);
|
|
28802
|
+
console.log("[AIAgentView] User authenticated:", session.user.id);
|
|
28803
|
+
} else {
|
|
28804
|
+
console.log("[AIAgentView] No authenticated session found");
|
|
28805
|
+
}
|
|
28806
|
+
};
|
|
28807
|
+
checkAuth();
|
|
28808
|
+
const supabase = _getSupabaseInstance();
|
|
28809
|
+
const { data: { subscription } } = supabase.auth.onAuthStateChange((event, session) => {
|
|
28810
|
+
if (session?.user) {
|
|
28811
|
+
setUserId(session.user.id);
|
|
28812
|
+
} else {
|
|
28813
|
+
setUserId(null);
|
|
28814
|
+
}
|
|
28815
|
+
});
|
|
28816
|
+
return () => {
|
|
28817
|
+
subscription.unsubscribe();
|
|
28818
|
+
};
|
|
28819
|
+
}, []);
|
|
28464
28820
|
const handleSubmit = async (e) => {
|
|
28465
28821
|
e.preventDefault();
|
|
28466
|
-
if (!inputValue.trim() ||
|
|
28822
|
+
if (!inputValue.trim() || !userId) return;
|
|
28823
|
+
let currentThreadId = activeThreadId || `temp-${Date.now()}`;
|
|
28824
|
+
if (isThreadLoading(currentThreadId)) return;
|
|
28467
28825
|
const userMessage = inputValue.trim();
|
|
28468
|
-
|
|
28469
|
-
|
|
28470
|
-
|
|
28826
|
+
setInputValue("");
|
|
28827
|
+
setLoadingThreads((prev) => new Set(prev).add(currentThreadId));
|
|
28828
|
+
setLastError(null);
|
|
28829
|
+
if (!activeThreadId) {
|
|
28830
|
+
setPendingThreadId(currentThreadId);
|
|
28831
|
+
}
|
|
28832
|
+
setStreamingStates((prev) => {
|
|
28833
|
+
const newMap = new Map(prev);
|
|
28834
|
+
newMap.set(currentThreadId, { message: "", reasoning: "" });
|
|
28835
|
+
return newMap;
|
|
28836
|
+
});
|
|
28837
|
+
const tempUserMessage = {
|
|
28838
|
+
id: Date.now(),
|
|
28839
|
+
// Temporary ID
|
|
28840
|
+
thread_id: activeThreadId || "",
|
|
28471
28841
|
role: "user",
|
|
28472
28842
|
content: userMessage,
|
|
28473
|
-
|
|
28843
|
+
reasoning: null,
|
|
28844
|
+
model_id: null,
|
|
28845
|
+
token_usage: null,
|
|
28846
|
+
metadata: null,
|
|
28847
|
+
created_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
28848
|
+
position: messages.length
|
|
28474
28849
|
};
|
|
28475
|
-
setMessages((prev) => [...prev,
|
|
28476
|
-
|
|
28477
|
-
setIsLoading(true);
|
|
28478
|
-
setIsTyping(true);
|
|
28479
|
-
setLastError(null);
|
|
28850
|
+
setMessages((prev) => [...prev, tempUserMessage]);
|
|
28851
|
+
setTimeout(scrollToBottom, 100);
|
|
28480
28852
|
try {
|
|
28481
|
-
|
|
28482
|
-
role: msg.role,
|
|
28483
|
-
content: msg.content
|
|
28484
|
-
}));
|
|
28485
|
-
const context = {
|
|
28486
|
-
timeframe: "flexible",
|
|
28487
|
-
focus: "conversational",
|
|
28488
|
-
conversation_style: "friendly_expert",
|
|
28489
|
-
system_prompt: `You are Axel, a friendly and knowledgeable manufacturing expert.
|
|
28490
|
-
|
|
28491
|
-
Your personality:
|
|
28492
|
-
- Warm, approachable, and professional
|
|
28493
|
-
- You respond naturally to greetings and casual conversation
|
|
28494
|
-
- You're passionate about manufacturing and love sharing your expertise
|
|
28495
|
-
- You can discuss any manufacturing topic across any timeframe
|
|
28496
|
-
|
|
28497
|
-
Guidelines:
|
|
28498
|
-
- Respond to greetings warmly (e.g., "Hi" \u2192 "Hi there! How can I help you with your manufacturing needs today?")
|
|
28499
|
-
- For manufacturing questions, provide detailed, actionable insights
|
|
28500
|
-
- You can analyze past data, current performance, or future projections
|
|
28501
|
-
- Always maintain a conversational tone while being informative
|
|
28502
|
-
- If asked about non-manufacturing topics, politely redirect to your expertise
|
|
28503
|
-
|
|
28504
|
-
Remember: You're not just an AI, you're Axel - a trusted manufacturing advisor who builds relationships with clients.`,
|
|
28505
|
-
conversation_history: conversationHistory,
|
|
28506
|
-
allow_any_timeframe: true,
|
|
28507
|
-
personality_traits: ["friendly", "expert", "conversational", "helpful"]
|
|
28508
|
-
};
|
|
28509
|
-
console.log("[AIAgentView] Submitting message:", {
|
|
28510
|
-
message: userMessage,
|
|
28511
|
-
lineId,
|
|
28512
|
-
shiftId,
|
|
28513
|
-
companyId,
|
|
28514
|
-
context
|
|
28515
|
-
});
|
|
28516
|
-
const result = await getManufacturingInsights(
|
|
28853
|
+
await sseClient.sendMessage(
|
|
28517
28854
|
userMessage,
|
|
28518
|
-
|
|
28519
|
-
|
|
28520
|
-
|
|
28521
|
-
|
|
28855
|
+
userId,
|
|
28856
|
+
activeThreadId || null,
|
|
28857
|
+
{
|
|
28858
|
+
companyId,
|
|
28859
|
+
lineId,
|
|
28860
|
+
shiftId
|
|
28861
|
+
},
|
|
28862
|
+
{
|
|
28863
|
+
onThreadCreated: (threadId) => {
|
|
28864
|
+
if (!activeThreadId) {
|
|
28865
|
+
const oldThreadId = currentThreadId;
|
|
28866
|
+
currentThreadId = threadId;
|
|
28867
|
+
setActiveThreadId(threadId);
|
|
28868
|
+
setPendingThreadId(null);
|
|
28869
|
+
setLoadingThreads((prev) => {
|
|
28870
|
+
const newSet = new Set(prev);
|
|
28871
|
+
if (newSet.has(oldThreadId)) {
|
|
28872
|
+
newSet.delete(oldThreadId);
|
|
28873
|
+
newSet.add(threadId);
|
|
28874
|
+
}
|
|
28875
|
+
return newSet;
|
|
28876
|
+
});
|
|
28877
|
+
setStreamingStates((prev) => {
|
|
28878
|
+
const newMap = new Map(prev);
|
|
28879
|
+
const streamingState = newMap.get(oldThreadId);
|
|
28880
|
+
if (streamingState) {
|
|
28881
|
+
newMap.delete(oldThreadId);
|
|
28882
|
+
newMap.set(threadId, streamingState);
|
|
28883
|
+
}
|
|
28884
|
+
return newMap;
|
|
28885
|
+
});
|
|
28886
|
+
mutateThreads();
|
|
28887
|
+
}
|
|
28888
|
+
},
|
|
28889
|
+
onMessage: (text) => {
|
|
28890
|
+
setStreamingStates((prev) => {
|
|
28891
|
+
const newMap = new Map(prev);
|
|
28892
|
+
const current = newMap.get(currentThreadId) || { message: "", reasoning: "" };
|
|
28893
|
+
newMap.set(currentThreadId, { ...current, message: current.message + text });
|
|
28894
|
+
return newMap;
|
|
28895
|
+
});
|
|
28896
|
+
},
|
|
28897
|
+
onReasoning: (text) => {
|
|
28898
|
+
setStreamingStates((prev) => {
|
|
28899
|
+
const newMap = new Map(prev);
|
|
28900
|
+
const current = newMap.get(currentThreadId) || { message: "", reasoning: "" };
|
|
28901
|
+
newMap.set(currentThreadId, { ...current, reasoning: current.reasoning + text });
|
|
28902
|
+
return newMap;
|
|
28903
|
+
});
|
|
28904
|
+
},
|
|
28905
|
+
onComplete: async (messageId) => {
|
|
28906
|
+
if (currentThreadId && !currentThreadId.startsWith("temp-")) {
|
|
28907
|
+
const updatedMessages = await getAllThreadMessages(currentThreadId);
|
|
28908
|
+
setMessages(updatedMessages);
|
|
28909
|
+
}
|
|
28910
|
+
setStreamingStates((prev) => {
|
|
28911
|
+
const newMap = new Map(prev);
|
|
28912
|
+
newMap.delete(currentThreadId);
|
|
28913
|
+
return newMap;
|
|
28914
|
+
});
|
|
28915
|
+
setLoadingThreads((prev) => {
|
|
28916
|
+
const newSet = new Set(prev);
|
|
28917
|
+
newSet.delete(currentThreadId);
|
|
28918
|
+
return newSet;
|
|
28919
|
+
});
|
|
28920
|
+
if (!activeThreadId) {
|
|
28921
|
+
setPendingThreadId(null);
|
|
28922
|
+
}
|
|
28923
|
+
},
|
|
28924
|
+
onError: (error) => {
|
|
28925
|
+
console.error("Chat error:", error);
|
|
28926
|
+
setLastError(error);
|
|
28927
|
+
setLoadingThreads((prev) => {
|
|
28928
|
+
const newSet = new Set(prev);
|
|
28929
|
+
newSet.delete(currentThreadId);
|
|
28930
|
+
return newSet;
|
|
28931
|
+
});
|
|
28932
|
+
setStreamingStates((prev) => {
|
|
28933
|
+
const newMap = new Map(prev);
|
|
28934
|
+
newMap.delete(currentThreadId);
|
|
28935
|
+
return newMap;
|
|
28936
|
+
});
|
|
28937
|
+
if (!activeThreadId) {
|
|
28938
|
+
setPendingThreadId(null);
|
|
28939
|
+
}
|
|
28940
|
+
setMessages((prev) => prev.slice(0, -1));
|
|
28941
|
+
}
|
|
28942
|
+
}
|
|
28522
28943
|
);
|
|
28523
|
-
if (result.success && result.analysis) {
|
|
28524
|
-
const assistantMessage = {
|
|
28525
|
-
id: Date.now().toString(),
|
|
28526
|
-
role: "assistant",
|
|
28527
|
-
content: result.analysis,
|
|
28528
|
-
timestamp: /* @__PURE__ */ new Date()
|
|
28529
|
-
};
|
|
28530
|
-
setMessages((prev) => [...prev, assistantMessage]);
|
|
28531
|
-
} else {
|
|
28532
|
-
const errorMessage = result.error || "Sorry, I encountered an error processing your request. Please try again.";
|
|
28533
|
-
const errorAssistantMessage = {
|
|
28534
|
-
id: Date.now().toString(),
|
|
28535
|
-
role: "assistant",
|
|
28536
|
-
content: errorMessage,
|
|
28537
|
-
timestamp: /* @__PURE__ */ new Date(),
|
|
28538
|
-
error: true
|
|
28539
|
-
};
|
|
28540
|
-
setMessages((prev) => [...prev, errorAssistantMessage]);
|
|
28541
|
-
setLastError(errorMessage);
|
|
28542
|
-
console.error("[AIAgentView] API returned error:", errorMessage);
|
|
28543
|
-
}
|
|
28544
28944
|
} catch (error) {
|
|
28545
|
-
console.error("[AIAgentView] Error
|
|
28546
|
-
const errorMessage =
|
|
28547
|
-
const errorAssistantMessage = {
|
|
28548
|
-
id: Date.now().toString(),
|
|
28549
|
-
role: "assistant",
|
|
28550
|
-
content: errorMessage,
|
|
28551
|
-
timestamp: /* @__PURE__ */ new Date(),
|
|
28552
|
-
error: true
|
|
28553
|
-
};
|
|
28554
|
-
setMessages((prev) => [...prev, errorAssistantMessage]);
|
|
28945
|
+
console.error("[AIAgentView] Error in chat:", error);
|
|
28946
|
+
const errorMessage = error instanceof Error ? error.message : "An unexpected error occurred";
|
|
28555
28947
|
setLastError(errorMessage);
|
|
28556
|
-
|
|
28557
|
-
|
|
28558
|
-
|
|
28948
|
+
setLoadingThreads((prev) => {
|
|
28949
|
+
const newSet = new Set(prev);
|
|
28950
|
+
newSet.delete(currentThreadId);
|
|
28951
|
+
return newSet;
|
|
28952
|
+
});
|
|
28953
|
+
setStreamingStates((prev) => {
|
|
28954
|
+
const newMap = new Map(prev);
|
|
28955
|
+
newMap.delete(currentThreadId);
|
|
28956
|
+
return newMap;
|
|
28957
|
+
});
|
|
28958
|
+
if (!activeThreadId) {
|
|
28959
|
+
setPendingThreadId(null);
|
|
28960
|
+
}
|
|
28961
|
+
setMessages((prev) => prev.slice(0, -1));
|
|
28559
28962
|
}
|
|
28560
28963
|
};
|
|
28561
28964
|
const handleKeyDown = (e) => {
|
|
@@ -28565,207 +28968,324 @@ var AIAgentView = () => {
|
|
|
28565
28968
|
}
|
|
28566
28969
|
};
|
|
28567
28970
|
const formatMessage = (content) => {
|
|
28568
|
-
|
|
28569
|
-
|
|
28570
|
-
|
|
28571
|
-
|
|
28971
|
+
const processInlineFormatting = (text) => {
|
|
28972
|
+
text = text.replace(/\*\*(.*?)\*\*/g, '<strong class="font-semibold text-gray-900">$1</strong>');
|
|
28973
|
+
text = text.replace(/`([^`]+)`/g, '<code class="bg-gray-100 px-1.5 py-0.5 rounded text-sm font-mono text-gray-800">$1</code>');
|
|
28974
|
+
return text;
|
|
28975
|
+
};
|
|
28976
|
+
const lines = content.split("\n");
|
|
28977
|
+
const formattedLines = [];
|
|
28978
|
+
let inList = false;
|
|
28979
|
+
for (let i = 0; i < lines.length; i++) {
|
|
28980
|
+
let line = lines[i];
|
|
28981
|
+
const trimmedLine = line.trim();
|
|
28982
|
+
if (!trimmedLine) {
|
|
28983
|
+
if (inList) {
|
|
28984
|
+
formattedLines.push("</ul>");
|
|
28985
|
+
inList = false;
|
|
28986
|
+
}
|
|
28987
|
+
formattedLines.push("<br/>");
|
|
28988
|
+
continue;
|
|
28572
28989
|
}
|
|
28573
|
-
if (
|
|
28574
|
-
|
|
28990
|
+
if (trimmedLine.startsWith("###")) {
|
|
28991
|
+
if (inList) {
|
|
28992
|
+
formattedLines.push("</ul>");
|
|
28993
|
+
inList = false;
|
|
28994
|
+
}
|
|
28995
|
+
const headerText = processInlineFormatting(trimmedLine.replace(/^###\s*/, ""));
|
|
28996
|
+
formattedLines.push(`<h3 class="text-lg font-semibold text-gray-900 mt-4 mb-2">${headerText}</h3>`);
|
|
28997
|
+
continue;
|
|
28998
|
+
} else if (trimmedLine.startsWith("##")) {
|
|
28999
|
+
if (inList) {
|
|
29000
|
+
formattedLines.push("</ul>");
|
|
29001
|
+
inList = false;
|
|
29002
|
+
}
|
|
29003
|
+
const headerText = processInlineFormatting(trimmedLine.replace(/^##\s*/, ""));
|
|
29004
|
+
formattedLines.push(`<h2 class="text-xl font-semibold text-gray-900 mt-4 mb-2">${headerText}</h2>`);
|
|
29005
|
+
continue;
|
|
29006
|
+
} else if (trimmedLine.startsWith("#")) {
|
|
29007
|
+
if (inList) {
|
|
29008
|
+
formattedLines.push("</ul>");
|
|
29009
|
+
inList = false;
|
|
29010
|
+
}
|
|
29011
|
+
const headerText = processInlineFormatting(trimmedLine.replace(/^#\s*/, ""));
|
|
29012
|
+
formattedLines.push(`<h1 class="text-2xl font-bold text-gray-900 mt-4 mb-3">${headerText}</h1>`);
|
|
29013
|
+
continue;
|
|
28575
29014
|
}
|
|
28576
|
-
|
|
28577
|
-
|
|
28578
|
-
|
|
28579
|
-
|
|
28580
|
-
|
|
28581
|
-
|
|
28582
|
-
|
|
28583
|
-
|
|
29015
|
+
const listMatch = trimmedLine.match(/^([-*•]\s+|\d+\.\s+|^\s*[-*•]\s+)/);
|
|
29016
|
+
if (listMatch) {
|
|
29017
|
+
if (!inList) {
|
|
29018
|
+
formattedLines.push('<ul class="space-y-1 mt-2 mb-2">');
|
|
29019
|
+
inList = true;
|
|
29020
|
+
}
|
|
29021
|
+
const listContent = processInlineFormatting(trimmedLine.replace(/^([-*•]\s+|\d+\.\s+|\s*[-*•]\s+)/, ""));
|
|
29022
|
+
formattedLines.push(`<li class="ml-4 text-gray-700 flex items-start"><span class="mr-2 text-gray-500">\u2022</span><span>${listContent}</span></li>`);
|
|
29023
|
+
continue;
|
|
29024
|
+
} else if (inList) {
|
|
29025
|
+
formattedLines.push("</ul>");
|
|
29026
|
+
inList = false;
|
|
29027
|
+
}
|
|
29028
|
+
if (trimmedLine.match(/^---+$/)) {
|
|
29029
|
+
formattedLines.push('<hr class="my-4 border-gray-200"/>');
|
|
29030
|
+
continue;
|
|
29031
|
+
}
|
|
29032
|
+
if (trimmedLine) {
|
|
29033
|
+
const processedLine = processInlineFormatting(line);
|
|
29034
|
+
if (trimmedLine.endsWith(":") && trimmedLine.length < 50 && !trimmedLine.includes("**")) {
|
|
29035
|
+
formattedLines.push(`<h3 class="text-lg font-semibold text-gray-900 mt-4 mb-2">${processedLine}</h3>`);
|
|
29036
|
+
} else {
|
|
29037
|
+
formattedLines.push(`<p class="text-gray-800 leading-relaxed mb-2">${processedLine}</p>`);
|
|
29038
|
+
}
|
|
29039
|
+
}
|
|
29040
|
+
}
|
|
29041
|
+
if (inList) {
|
|
29042
|
+
formattedLines.push("</ul>");
|
|
29043
|
+
}
|
|
29044
|
+
return formattedLines.join("");
|
|
28584
29045
|
};
|
|
28585
29046
|
const formatTime2 = (timestamp) => {
|
|
28586
|
-
|
|
29047
|
+
const date = new Date(timestamp);
|
|
29048
|
+
return date.toLocaleTimeString([], {
|
|
28587
29049
|
hour: "2-digit",
|
|
28588
29050
|
minute: "2-digit",
|
|
28589
29051
|
hour12: false
|
|
28590
29052
|
});
|
|
28591
29053
|
};
|
|
28592
|
-
|
|
28593
|
-
|
|
28594
|
-
|
|
28595
|
-
|
|
28596
|
-
|
|
28597
|
-
|
|
28598
|
-
|
|
28599
|
-
|
|
28600
|
-
|
|
28601
|
-
|
|
28602
|
-
|
|
28603
|
-
|
|
28604
|
-
|
|
28605
|
-
|
|
28606
|
-
|
|
28607
|
-
|
|
28608
|
-
|
|
28609
|
-
|
|
28610
|
-
|
|
28611
|
-
|
|
28612
|
-
|
|
28613
|
-
|
|
28614
|
-
] }) }) }),
|
|
28615
|
-
/* @__PURE__ */ jsx(
|
|
28616
|
-
"main",
|
|
29054
|
+
const displayMessages = [...messages];
|
|
29055
|
+
const effectiveThreadId = activeThreadId || pendingThreadId || void 0;
|
|
29056
|
+
const currentStreaming = getStreamingState(effectiveThreadId);
|
|
29057
|
+
const isCurrentThreadLoading = isThreadLoading(effectiveThreadId);
|
|
29058
|
+
if (isCurrentThreadLoading && currentStreaming.message) {
|
|
29059
|
+
displayMessages.push({
|
|
29060
|
+
id: -1,
|
|
29061
|
+
// Use -1 for streaming message to identify it
|
|
29062
|
+
thread_id: activeThreadId || "",
|
|
29063
|
+
role: "assistant",
|
|
29064
|
+
content: currentStreaming.message,
|
|
29065
|
+
reasoning: currentStreaming.reasoning || null,
|
|
29066
|
+
model_id: "gpt-4o-mini",
|
|
29067
|
+
token_usage: null,
|
|
29068
|
+
metadata: null,
|
|
29069
|
+
created_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
29070
|
+
position: messages.length
|
|
29071
|
+
});
|
|
29072
|
+
}
|
|
29073
|
+
return /* @__PURE__ */ jsxs("div", { className: "flex h-screen bg-white", children: [
|
|
29074
|
+
/* @__PURE__ */ jsx("div", { className: `${isSidebarOpen ? "w-80" : "w-0"} transition-all duration-300 overflow-hidden flex-shrink-0`, children: /* @__PURE__ */ jsx(
|
|
29075
|
+
ThreadSidebar,
|
|
28617
29076
|
{
|
|
28618
|
-
|
|
28619
|
-
|
|
28620
|
-
|
|
28621
|
-
|
|
28622
|
-
|
|
28623
|
-
|
|
28624
|
-
|
|
28625
|
-
|
|
28626
|
-
|
|
28627
|
-
|
|
28628
|
-
|
|
28629
|
-
|
|
28630
|
-
|
|
28631
|
-
|
|
28632
|
-
|
|
28633
|
-
|
|
28634
|
-
|
|
28635
|
-
|
|
28636
|
-
|
|
28637
|
-
|
|
28638
|
-
|
|
28639
|
-
|
|
28640
|
-
|
|
28641
|
-
|
|
28642
|
-
|
|
28643
|
-
|
|
28644
|
-
|
|
28645
|
-
|
|
28646
|
-
|
|
28647
|
-
|
|
28648
|
-
|
|
28649
|
-
|
|
28650
|
-
|
|
28651
|
-
|
|
28652
|
-
|
|
28653
|
-
|
|
28654
|
-
|
|
28655
|
-
|
|
28656
|
-
|
|
28657
|
-
|
|
28658
|
-
|
|
28659
|
-
|
|
28660
|
-
|
|
28661
|
-
|
|
28662
|
-
|
|
28663
|
-
|
|
28664
|
-
|
|
28665
|
-
|
|
28666
|
-
}
|
|
28667
|
-
),
|
|
28668
|
-
message.role === "assistant" && !message.error && /* @__PURE__ */ jsx(
|
|
28669
|
-
"button",
|
|
28670
|
-
{
|
|
28671
|
-
onClick: () => copyToClipboard(message.content, message.id),
|
|
28672
|
-
className: "absolute top-3 right-3 opacity-0 group-hover:opacity-100 transition-opacity duration-200 p-1.5 hover:bg-gray-100 rounded-lg",
|
|
28673
|
-
title: "Copy message",
|
|
28674
|
-
children: copiedMessageId === message.id ? /* @__PURE__ */ jsx(Check, { className: "w-4 h-4 text-green-600" }) : /* @__PURE__ */ jsx(Copy, { className: "w-4 h-4 text-gray-500" })
|
|
28675
|
-
}
|
|
28676
|
-
)
|
|
28677
|
-
]
|
|
28678
|
-
}
|
|
28679
|
-
),
|
|
28680
|
-
/* @__PURE__ */ jsxs("div", { className: `mt-2 flex items-center gap-2 text-xs text-gray-400 ${message.role === "user" ? "justify-end" : "justify-start"}`, children: [
|
|
28681
|
-
/* @__PURE__ */ jsx("span", { children: formatTime2(message.timestamp) }),
|
|
28682
|
-
message.role === "assistant" && !message.error && /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1", children: [
|
|
28683
|
-
/* @__PURE__ */ jsx("div", { className: "w-1 h-1 bg-gray-300 rounded-full" }),
|
|
28684
|
-
/* @__PURE__ */ jsx("span", { children: "Axel" })
|
|
28685
|
-
] })
|
|
28686
|
-
] })
|
|
28687
|
-
] }),
|
|
28688
|
-
message.role === "user" && /* @__PURE__ */ jsx("div", { className: "flex-shrink-0", children: /* @__PURE__ */ jsx("div", { className: "w-10 h-10 bg-gray-700 text-white rounded-xl flex items-center justify-center text-sm font-semibold", children: entityConfig.companyId?.charAt(0).toUpperCase() || "U" }) })
|
|
28689
|
-
]
|
|
28690
|
-
},
|
|
28691
|
-
message.id
|
|
28692
|
-
)),
|
|
28693
|
-
isLoading && /* @__PURE__ */ jsxs("div", { className: "flex gap-4 justify-start", children: [
|
|
28694
|
-
/* @__PURE__ */ jsx("div", { className: "flex-shrink-0", children: /* @__PURE__ */ jsx("div", { className: "w-12 h-12 rounded-xl overflow-hidden shadow-sm", children: /* @__PURE__ */ jsx(
|
|
29077
|
+
activeThreadId,
|
|
29078
|
+
onSelectThread: setActiveThreadId,
|
|
29079
|
+
onNewThread: handleNewThread,
|
|
29080
|
+
className: "h-full"
|
|
29081
|
+
}
|
|
29082
|
+
) }),
|
|
29083
|
+
/* @__PURE__ */ jsxs("div", { className: "flex-1 flex flex-col", children: [
|
|
29084
|
+
/* @__PURE__ */ jsx("header", { className: "flex-shrink-0 bg-white border-b border-gray-200", children: /* @__PURE__ */ jsx("div", { className: "px-6 py-4", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
|
|
29085
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-4", children: [
|
|
29086
|
+
/* @__PURE__ */ jsx(
|
|
29087
|
+
"button",
|
|
29088
|
+
{
|
|
29089
|
+
onClick: () => setIsSidebarOpen(!isSidebarOpen),
|
|
29090
|
+
className: "p-2 hover:bg-gray-100 rounded-lg transition-colors",
|
|
29091
|
+
"aria-label": "Toggle sidebar",
|
|
29092
|
+
children: isSidebarOpen ? /* @__PURE__ */ jsx(X, { className: "w-5 h-5" }) : /* @__PURE__ */ jsx(Menu, { className: "w-5 h-5" })
|
|
29093
|
+
}
|
|
29094
|
+
),
|
|
29095
|
+
/* @__PURE__ */ jsxs(
|
|
29096
|
+
"button",
|
|
29097
|
+
{
|
|
29098
|
+
onClick: () => navigate("/"),
|
|
29099
|
+
className: "flex items-center gap-2 text-gray-600 hover:text-gray-900 transition-colors",
|
|
29100
|
+
"aria-label": "Go back",
|
|
29101
|
+
children: [
|
|
29102
|
+
/* @__PURE__ */ jsx(ArrowLeft, { className: "w-5 h-5" }),
|
|
29103
|
+
/* @__PURE__ */ jsx("span", { className: "text-sm font-medium", children: "Back" })
|
|
29104
|
+
]
|
|
29105
|
+
}
|
|
29106
|
+
)
|
|
29107
|
+
] }),
|
|
29108
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center", children: [
|
|
29109
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3", children: [
|
|
29110
|
+
/* @__PURE__ */ jsx("h1", { className: "text-xl sm:text-2xl md:text-3xl font-bold text-gray-800 tracking-tight leading-none", children: "Axel - AI Manufacturing Expert" }),
|
|
29111
|
+
/* @__PURE__ */ jsx("div", { className: "h-2 w-2 rounded-full bg-blue-500 animate-pulse ring-2 ring-blue-500/30" })
|
|
29112
|
+
] }),
|
|
29113
|
+
/* @__PURE__ */ jsx("div", { className: "flex items-center mt-1", children: /* @__PURE__ */ jsx("span", { className: "text-xs font-medium text-gray-500", children: /* @__PURE__ */ jsx(ISTTimer_default, {}) }) })
|
|
29114
|
+
] }),
|
|
29115
|
+
/* @__PURE__ */ jsx("div", { className: "w-24" })
|
|
29116
|
+
] }) }) }),
|
|
29117
|
+
/* @__PURE__ */ jsx(
|
|
29118
|
+
"main",
|
|
29119
|
+
{
|
|
29120
|
+
ref: containerRef,
|
|
29121
|
+
className: "flex-1 overflow-y-auto bg-gray-50/50 min-h-0",
|
|
29122
|
+
children: /* @__PURE__ */ jsxs("div", { className: "max-w-5xl mx-auto p-4 sm:p-6 md:p-8", children: [
|
|
29123
|
+
displayMessages.length === 0 && /* @__PURE__ */ jsx("div", { className: "mb-8 bg-white border border-gray-200/80 shadow-sm rounded-2xl p-6 sm:p-8", children: /* @__PURE__ */ jsxs("div", { className: "flex items-start gap-4", children: [
|
|
29124
|
+
/* @__PURE__ */ jsx("div", { className: "w-16 h-16 rounded-xl overflow-hidden shadow-sm flex-shrink-0", children: /* @__PURE__ */ jsx(
|
|
28695
29125
|
"img",
|
|
28696
29126
|
{
|
|
28697
29127
|
src: axelProfilePng,
|
|
28698
|
-
alt: "Axel",
|
|
29128
|
+
alt: "Axel - AI Manufacturing Expert",
|
|
28699
29129
|
className: "w-full h-full object-cover"
|
|
28700
29130
|
}
|
|
28701
|
-
) })
|
|
28702
|
-
/* @__PURE__ */
|
|
28703
|
-
/* @__PURE__ */
|
|
28704
|
-
|
|
28705
|
-
|
|
28706
|
-
|
|
28707
|
-
|
|
28708
|
-
|
|
28709
|
-
|
|
28710
|
-
|
|
28711
|
-
|
|
29131
|
+
) }),
|
|
29132
|
+
/* @__PURE__ */ jsxs("div", { className: "flex-1 pt-1", children: [
|
|
29133
|
+
/* @__PURE__ */ jsx("h2", { className: "text-xl font-semibold text-gray-900 mb-2", children: "Hi, I'm Axel - Your AI Supervisor" }),
|
|
29134
|
+
/* @__PURE__ */ jsx("p", { className: "text-gray-600 leading-relaxed", children: "Ask me anything about your shop-floor. I'll remember our conversation and help you optimize your manufacturing processes." })
|
|
29135
|
+
] })
|
|
29136
|
+
] }) }),
|
|
29137
|
+
/* @__PURE__ */ jsxs("div", { className: "space-y-6", children: [
|
|
29138
|
+
displayMessages.map((message, index) => /* @__PURE__ */ jsxs(
|
|
29139
|
+
"div",
|
|
29140
|
+
{
|
|
29141
|
+
className: `flex gap-4 ${message.role === "user" ? "justify-end" : "justify-start"}`,
|
|
29142
|
+
children: [
|
|
29143
|
+
message.role === "assistant" && /* @__PURE__ */ jsx("div", { className: "flex-shrink-0", children: /* @__PURE__ */ jsx("div", { className: "w-12 h-12 rounded-xl overflow-hidden shadow-sm", children: /* @__PURE__ */ jsx(
|
|
29144
|
+
"img",
|
|
29145
|
+
{
|
|
29146
|
+
src: axelProfilePng,
|
|
29147
|
+
alt: "Axel",
|
|
29148
|
+
className: "w-full h-full object-cover"
|
|
29149
|
+
}
|
|
29150
|
+
) }) }),
|
|
29151
|
+
/* @__PURE__ */ jsxs("div", { className: `max-w-[75%] group ${message.role === "user" ? "order-1" : ""}`, children: [
|
|
29152
|
+
/* @__PURE__ */ jsxs(
|
|
29153
|
+
"div",
|
|
29154
|
+
{
|
|
29155
|
+
className: `relative px-5 py-4 rounded-2xl shadow-sm ${message.role === "user" ? "bg-blue-600 text-white" : "bg-white border border-gray-200/80"}`,
|
|
29156
|
+
children: [
|
|
29157
|
+
/* @__PURE__ */ jsxs("div", { className: `${message.role === "user" ? "text-white" : "text-gray-800"}`, children: [
|
|
29158
|
+
message.role === "assistant" ? /* @__PURE__ */ jsx(
|
|
29159
|
+
"div",
|
|
29160
|
+
{
|
|
29161
|
+
className: "formatted-content",
|
|
29162
|
+
dangerouslySetInnerHTML: {
|
|
29163
|
+
__html: formatMessage(message.content)
|
|
29164
|
+
}
|
|
29165
|
+
}
|
|
29166
|
+
) : /* @__PURE__ */ jsx("div", { className: "whitespace-pre-wrap leading-relaxed", children: message.content }),
|
|
29167
|
+
message.id === -1 && /* @__PURE__ */ jsx("span", { className: "inline-block w-0.5 h-4 bg-gray-400 animate-pulse ml-0.5" })
|
|
29168
|
+
] }),
|
|
29169
|
+
message.role === "assistant" && message.id !== -1 && /* @__PURE__ */ jsx(
|
|
29170
|
+
"button",
|
|
29171
|
+
{
|
|
29172
|
+
onClick: () => copyToClipboard(message.content, message.id.toString()),
|
|
29173
|
+
className: "absolute top-3 right-3 opacity-0 group-hover:opacity-100 transition-opacity duration-200 p-1.5 hover:bg-gray-100 rounded-lg",
|
|
29174
|
+
title: "Copy message",
|
|
29175
|
+
children: copiedMessageId === message.id.toString() ? /* @__PURE__ */ jsx(Check, { className: "w-4 h-4 text-green-600" }) : /* @__PURE__ */ jsx(Copy, { className: "w-4 h-4 text-gray-500" })
|
|
29176
|
+
}
|
|
29177
|
+
),
|
|
29178
|
+
message.reasoning && /* @__PURE__ */ jsxs("details", { className: "mt-3 pt-3 border-t border-gray-200", children: [
|
|
29179
|
+
/* @__PURE__ */ jsx("summary", { className: "cursor-pointer text-sm text-gray-600 hover:text-gray-800", children: "View reasoning" }),
|
|
29180
|
+
/* @__PURE__ */ jsx("div", { className: "mt-2 text-sm text-gray-600", children: message.reasoning })
|
|
29181
|
+
] })
|
|
29182
|
+
]
|
|
29183
|
+
}
|
|
29184
|
+
),
|
|
29185
|
+
/* @__PURE__ */ jsxs("div", { className: `mt-2 flex items-center gap-2 text-xs text-gray-400 ${message.role === "user" ? "justify-end" : "justify-start"}`, children: [
|
|
29186
|
+
/* @__PURE__ */ jsx("span", { children: formatTime2(message.created_at) }),
|
|
29187
|
+
message.role === "assistant" && message.id !== -1 && /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1", children: [
|
|
29188
|
+
/* @__PURE__ */ jsx("div", { className: "w-1 h-1 bg-gray-300 rounded-full" }),
|
|
29189
|
+
/* @__PURE__ */ jsx("span", { children: "Axel" })
|
|
29190
|
+
] })
|
|
29191
|
+
] })
|
|
29192
|
+
] }),
|
|
29193
|
+
message.role === "user" && /* @__PURE__ */ jsx("div", { className: "flex-shrink-0", children: /* @__PURE__ */ jsx("div", { className: "w-10 h-10 bg-gray-700 text-white rounded-xl flex items-center justify-center text-sm font-semibold", children: entityConfig.companyId?.charAt(0).toUpperCase() || "U" }) })
|
|
29194
|
+
]
|
|
29195
|
+
},
|
|
29196
|
+
message.id === -1 ? `streaming-${currentStreaming.message.length}` : `${message.id}-${index}`
|
|
29197
|
+
)),
|
|
29198
|
+
lastError && /* @__PURE__ */ jsxs("div", { className: "flex gap-4 justify-start", children: [
|
|
29199
|
+
/* @__PURE__ */ jsx("div", { className: "flex-shrink-0", children: /* @__PURE__ */ jsx("div", { className: "w-12 h-12 rounded-xl bg-red-100 flex items-center justify-center", children: /* @__PURE__ */ jsx(AlertCircle, { className: "w-6 h-6 text-red-600" }) }) }),
|
|
29200
|
+
/* @__PURE__ */ jsxs("div", { className: "bg-red-50 border border-red-200 px-5 py-4 rounded-2xl shadow-sm max-w-[75%]", children: [
|
|
29201
|
+
/* @__PURE__ */ jsx("p", { className: "text-red-800 text-sm", children: lastError }),
|
|
29202
|
+
/* @__PURE__ */ jsx(
|
|
29203
|
+
"button",
|
|
29204
|
+
{
|
|
29205
|
+
onClick: () => setLastError(null),
|
|
29206
|
+
className: "mt-2 text-xs text-red-600 hover:text-red-800 underline",
|
|
29207
|
+
children: "Dismiss"
|
|
29208
|
+
}
|
|
29209
|
+
)
|
|
29210
|
+
] })
|
|
29211
|
+
] }),
|
|
29212
|
+
isCurrentThreadLoading && !currentStreaming.message && /* @__PURE__ */ jsxs("div", { className: "flex gap-4 justify-start", children: [
|
|
29213
|
+
/* @__PURE__ */ jsx("div", { className: "flex-shrink-0", children: /* @__PURE__ */ jsx("div", { className: "w-12 h-12 rounded-xl overflow-hidden shadow-sm", children: /* @__PURE__ */ jsx(
|
|
29214
|
+
"img",
|
|
29215
|
+
{
|
|
29216
|
+
src: axelProfilePng,
|
|
29217
|
+
alt: "Axel",
|
|
29218
|
+
className: "w-full h-full object-cover"
|
|
29219
|
+
}
|
|
29220
|
+
) }) }),
|
|
29221
|
+
/* @__PURE__ */ jsx("div", { className: "bg-white border border-gray-200/80 px-5 py-4 rounded-2xl shadow-sm max-w-[75%]", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3", children: [
|
|
29222
|
+
/* @__PURE__ */ jsxs("div", { className: "flex space-x-1", children: [
|
|
29223
|
+
/* @__PURE__ */ jsx("div", { className: "w-2 h-2 bg-blue-500 rounded-full animate-bounce" }),
|
|
29224
|
+
/* @__PURE__ */ jsx("div", { className: "w-2 h-2 bg-blue-500 rounded-full animate-bounce", style: { animationDelay: "0.1s" } }),
|
|
29225
|
+
/* @__PURE__ */ jsx("div", { className: "w-2 h-2 bg-blue-500 rounded-full animate-bounce", style: { animationDelay: "0.2s" } })
|
|
29226
|
+
] }),
|
|
29227
|
+
/* @__PURE__ */ jsx("span", { className: "text-gray-600 text-sm", children: "Axel is analyzing your request..." })
|
|
29228
|
+
] }) })
|
|
29229
|
+
] }),
|
|
29230
|
+
/* @__PURE__ */ jsx("div", { ref: messagesEndRef })
|
|
29231
|
+
] })
|
|
28712
29232
|
] })
|
|
28713
|
-
] })
|
|
28714
|
-
}
|
|
28715
|
-
),
|
|
28716
|
-
/* @__PURE__ */ jsx("footer", { className: "flex-shrink-0 border-t border-gray-200 bg-white sticky bottom-0", children: /* @__PURE__ */ jsxs("div", { className: "max-w-5xl mx-auto p-4 sm:p-6", children: [
|
|
28717
|
-
messages.length > 0 && /* @__PURE__ */ jsx("div", { className: "flex justify-center mb-4", children: /* @__PURE__ */ jsxs(
|
|
28718
|
-
"button",
|
|
28719
|
-
{
|
|
28720
|
-
onClick: clearConversation,
|
|
28721
|
-
className: "inline-flex items-center gap-2 px-3 py-1.5 text-xs font-medium text-gray-500 hover:text-gray-700 hover:bg-gray-100 rounded-lg transition-colors",
|
|
28722
|
-
children: [
|
|
28723
|
-
/* @__PURE__ */ jsx(RefreshCw, { className: "w-3.5 h-3.5" }),
|
|
28724
|
-
"Clear conversation"
|
|
28725
|
-
]
|
|
28726
29233
|
}
|
|
28727
|
-
)
|
|
28728
|
-
/* @__PURE__ */
|
|
28729
|
-
/* @__PURE__ */
|
|
28730
|
-
|
|
28731
|
-
|
|
28732
|
-
|
|
29234
|
+
),
|
|
29235
|
+
/* @__PURE__ */ jsx("footer", { className: "flex-shrink-0 border-t border-gray-200 bg-white sticky bottom-0", children: /* @__PURE__ */ jsxs("div", { className: "max-w-5xl mx-auto p-4 sm:p-6", children: [
|
|
29236
|
+
activeThreadId && messages.length > 0 && /* @__PURE__ */ jsx("div", { className: "flex justify-center mb-4", children: /* @__PURE__ */ jsxs(
|
|
29237
|
+
"button",
|
|
29238
|
+
{
|
|
29239
|
+
onClick: handleNewThread,
|
|
29240
|
+
className: "inline-flex items-center gap-2 px-3 py-1.5 text-xs font-medium text-gray-500 hover:text-gray-700 hover:bg-gray-100 rounded-lg transition-colors",
|
|
29241
|
+
children: [
|
|
29242
|
+
/* @__PURE__ */ jsx(RefreshCw, { className: "w-3.5 h-3.5" }),
|
|
29243
|
+
"New conversation"
|
|
29244
|
+
]
|
|
29245
|
+
}
|
|
29246
|
+
) }),
|
|
29247
|
+
/* @__PURE__ */ jsxs("form", { onSubmit: handleSubmit, className: "space-y-3", children: [
|
|
29248
|
+
/* @__PURE__ */ jsxs("div", { className: "flex gap-3 items-end", children: [
|
|
29249
|
+
/* @__PURE__ */ jsxs("div", { className: "flex-1 relative", children: [
|
|
29250
|
+
/* @__PURE__ */ jsx(
|
|
29251
|
+
"textarea",
|
|
29252
|
+
{
|
|
29253
|
+
ref: textareaRef,
|
|
29254
|
+
value: inputValue,
|
|
29255
|
+
onChange: (e) => setInputValue(e.target.value),
|
|
29256
|
+
onKeyDown: handleKeyDown,
|
|
29257
|
+
placeholder: "Ask me about production optimization, quality metrics, or any manufacturing challenge...",
|
|
29258
|
+
className: "w-full resize-none rounded-xl border border-gray-300 px-4 py-3.5 pr-16 focus:outline-none focus:ring-2 focus:ring-blue-500/20 focus:border-blue-400 bg-white placeholder-gray-500 text-gray-900 text-sm leading-relaxed shadow-sm transition-all duration-200",
|
|
29259
|
+
rows: 1,
|
|
29260
|
+
disabled: isCurrentThreadLoading,
|
|
29261
|
+
style: { minHeight: "48px", maxHeight: "120px" }
|
|
29262
|
+
}
|
|
29263
|
+
),
|
|
29264
|
+
/* @__PURE__ */ jsx("div", { className: "absolute bottom-3 right-3 flex items-center gap-2", children: inputValue.length > 0 && /* @__PURE__ */ jsx("span", { className: "text-xs text-gray-400 font-mono", children: inputValue.length }) })
|
|
29265
|
+
] }),
|
|
29266
|
+
/* @__PURE__ */ jsxs(
|
|
29267
|
+
"button",
|
|
28733
29268
|
{
|
|
28734
|
-
|
|
28735
|
-
|
|
28736
|
-
|
|
28737
|
-
|
|
28738
|
-
|
|
28739
|
-
|
|
28740
|
-
|
|
28741
|
-
disabled: isLoading,
|
|
28742
|
-
style: { minHeight: "48px", maxHeight: "120px" }
|
|
29269
|
+
type: "submit",
|
|
29270
|
+
disabled: !inputValue.trim() || isCurrentThreadLoading,
|
|
29271
|
+
className: "inline-flex items-center justify-center gap-2 h-12 px-5 bg-blue-600 text-white rounded-xl hover:bg-blue-700 transition-all duration-200 text-sm font-medium disabled:opacity-50 disabled:cursor-not-allowed focus:outline-none focus:ring-2 focus:ring-blue-500/20 focus:ring-offset-2 shadow-sm hover:shadow-md disabled:hover:shadow-sm",
|
|
29272
|
+
children: [
|
|
29273
|
+
/* @__PURE__ */ jsx(Send, { className: "w-4 h-4" }),
|
|
29274
|
+
/* @__PURE__ */ jsx("span", { className: "hidden sm:inline", children: "Send" })
|
|
29275
|
+
]
|
|
28743
29276
|
}
|
|
28744
|
-
)
|
|
28745
|
-
/* @__PURE__ */ jsx("div", { className: "absolute bottom-3 right-3 flex items-center gap-2", children: inputValue.length > 0 && /* @__PURE__ */ jsx("span", { className: "text-xs text-gray-400 font-mono", children: inputValue.length }) })
|
|
29277
|
+
)
|
|
28746
29278
|
] }),
|
|
28747
|
-
/* @__PURE__ */ jsxs(
|
|
28748
|
-
"
|
|
28749
|
-
{
|
|
28750
|
-
|
|
28751
|
-
|
|
28752
|
-
|
|
28753
|
-
|
|
28754
|
-
isLoading ? /* @__PURE__ */ jsx(Loader2, { className: "w-4 h-4 animate-spin" }) : /* @__PURE__ */ jsx(Send, { className: "w-4 h-4" }),
|
|
28755
|
-
/* @__PURE__ */ jsx("span", { className: "hidden sm:inline", children: isLoading ? "Sending..." : "Send" })
|
|
28756
|
-
]
|
|
28757
|
-
}
|
|
28758
|
-
)
|
|
28759
|
-
] }),
|
|
28760
|
-
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between text-xs text-gray-400", children: [
|
|
28761
|
-
/* @__PURE__ */ jsx("div", { className: "flex items-center gap-4", children: /* @__PURE__ */ jsx("span", { children: "Press Enter to send \u2022 Shift+Enter for new line" }) }),
|
|
28762
|
-
/* @__PURE__ */ jsx("div", { className: "flex items-center gap-2", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1", children: [
|
|
28763
|
-
/* @__PURE__ */ jsx("div", { className: "w-1.5 h-1.5 bg-green-500 rounded-full" }),
|
|
28764
|
-
/* @__PURE__ */ jsx("span", { children: "Connected" })
|
|
28765
|
-
] }) })
|
|
29279
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between text-xs text-gray-400", children: [
|
|
29280
|
+
/* @__PURE__ */ jsx("div", { className: "flex items-center gap-4", children: /* @__PURE__ */ jsx("span", { children: "Press Enter to send \u2022 Shift+Enter for new line" }) }),
|
|
29281
|
+
/* @__PURE__ */ jsx("div", { className: "flex items-center gap-2", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1", children: [
|
|
29282
|
+
/* @__PURE__ */ jsx("div", { className: "w-1.5 h-1.5 bg-green-500 rounded-full" }),
|
|
29283
|
+
/* @__PURE__ */ jsx("span", { children: "Connected" })
|
|
29284
|
+
] }) })
|
|
29285
|
+
] })
|
|
28766
29286
|
] })
|
|
28767
|
-
] })
|
|
28768
|
-
] })
|
|
29287
|
+
] }) })
|
|
29288
|
+
] })
|
|
28769
29289
|
] });
|
|
28770
29290
|
};
|
|
28771
29291
|
var AIAgentView_default = AIAgentView;
|
|
@@ -31214,10 +31734,7 @@ var ShiftsView = ({
|
|
|
31214
31734
|
}
|
|
31215
31735
|
),
|
|
31216
31736
|
/* @__PURE__ */ jsxs("div", { className: "flex-1 flex flex-col items-center", children: [
|
|
31217
|
-
/* @__PURE__ */
|
|
31218
|
-
/* @__PURE__ */ jsx("h1", { className: "text-xl sm:text-2xl md:text-3xl font-bold text-gray-800 tracking-tight leading-none", children: "Shift Management" }),
|
|
31219
|
-
/* @__PURE__ */ jsx("div", { className: "h-2 w-2 rounded-full bg-blue-500 animate-pulse ring-2 ring-blue-500/30" })
|
|
31220
|
-
] }),
|
|
31737
|
+
/* @__PURE__ */ jsx("div", { className: "flex items-center", children: /* @__PURE__ */ jsx("h1", { className: "text-xl sm:text-2xl md:text-3xl font-bold text-gray-800 tracking-tight leading-none", children: "Shift Management" }) }),
|
|
31221
31738
|
/* @__PURE__ */ jsx("div", { className: "flex items-center mt-1", children: /* @__PURE__ */ jsx("span", { className: "text-xs font-medium text-gray-500", children: /* @__PURE__ */ jsx(ISTTimer_default, {}) }) })
|
|
31222
31739
|
] }),
|
|
31223
31740
|
/* @__PURE__ */ jsx("div", { className: "absolute right-0 w-24" })
|
|
@@ -33518,8 +34035,133 @@ var S3Service = class {
|
|
|
33518
34035
|
}
|
|
33519
34036
|
}
|
|
33520
34037
|
};
|
|
34038
|
+
|
|
34039
|
+
// src/lib/api/optifye-agent.ts
|
|
34040
|
+
var OPTIFYE_API_URL = "https://optifye-agent-production.up.railway.app";
|
|
34041
|
+
var OptifyeAgentClient = class {
|
|
34042
|
+
constructor(apiUrl = OPTIFYE_API_URL) {
|
|
34043
|
+
this.apiUrl = apiUrl;
|
|
34044
|
+
}
|
|
34045
|
+
/**
|
|
34046
|
+
* Call Optifye Agent for manufacturing analysis
|
|
34047
|
+
*/
|
|
34048
|
+
async getManufacturingInsights(userQuestion, lineId, shiftId, companyId, context) {
|
|
34049
|
+
try {
|
|
34050
|
+
const requestData = {
|
|
34051
|
+
prompt: userQuestion,
|
|
34052
|
+
line_id: lineId,
|
|
34053
|
+
shift_id: shiftId,
|
|
34054
|
+
company_id: companyId
|
|
34055
|
+
};
|
|
34056
|
+
if (context) {
|
|
34057
|
+
requestData.context = context;
|
|
34058
|
+
}
|
|
34059
|
+
console.log("[OptifyeAgent] Sending request:", requestData);
|
|
34060
|
+
const response = await fetch(`${this.apiUrl}/api/custom-analysis`, {
|
|
34061
|
+
method: "POST",
|
|
34062
|
+
headers: {
|
|
34063
|
+
"Content-Type": "application/json"
|
|
34064
|
+
},
|
|
34065
|
+
body: JSON.stringify(requestData),
|
|
34066
|
+
signal: AbortSignal.timeout(6e4)
|
|
34067
|
+
// 60 second timeout
|
|
34068
|
+
});
|
|
34069
|
+
const responseText = await response.text();
|
|
34070
|
+
console.log("[OptifyeAgent] Response status:", response.status);
|
|
34071
|
+
console.log("[OptifyeAgent] Response text:", responseText);
|
|
34072
|
+
let result;
|
|
34073
|
+
try {
|
|
34074
|
+
result = JSON.parse(responseText);
|
|
34075
|
+
} catch (parseError) {
|
|
34076
|
+
console.error("[OptifyeAgent] Failed to parse response as JSON:", parseError);
|
|
34077
|
+
if (responseText.includes("'Agent' object has no attribute")) {
|
|
34078
|
+
return {
|
|
34079
|
+
success: false,
|
|
34080
|
+
error: "Server error: The AI agent service is experiencing issues. Please try again later or contact support."
|
|
34081
|
+
};
|
|
34082
|
+
}
|
|
34083
|
+
return {
|
|
34084
|
+
success: false,
|
|
34085
|
+
error: `Invalid response format from server: ${responseText.substring(0, 200)}`
|
|
34086
|
+
};
|
|
34087
|
+
}
|
|
34088
|
+
if (response.ok) {
|
|
34089
|
+
return {
|
|
34090
|
+
success: result.success ?? true,
|
|
34091
|
+
analysis: result.analysis || result.response || result.message || result.data,
|
|
34092
|
+
timestamp: result.timestamp,
|
|
34093
|
+
error: result.error
|
|
34094
|
+
};
|
|
34095
|
+
} else {
|
|
34096
|
+
const errorMsg = result.error || result.message || `API request failed: ${response.status}`;
|
|
34097
|
+
console.error("[OptifyeAgent] API error:", errorMsg);
|
|
34098
|
+
if (errorMsg.includes("'Agent' object has no attribute")) {
|
|
34099
|
+
return {
|
|
34100
|
+
success: false,
|
|
34101
|
+
error: "The AI service is currently being updated. Please try again in a few moments."
|
|
34102
|
+
};
|
|
34103
|
+
}
|
|
34104
|
+
return {
|
|
34105
|
+
success: false,
|
|
34106
|
+
error: errorMsg
|
|
34107
|
+
};
|
|
34108
|
+
}
|
|
34109
|
+
} catch (error) {
|
|
34110
|
+
const errorMsg = error instanceof Error ? `Failed to connect to Optifye Agent: ${error.message}` : "Failed to connect to Optifye Agent";
|
|
34111
|
+
console.error("[OptifyeAgent] Request failed:", error);
|
|
34112
|
+
if (error instanceof Error && error.name === "AbortError") {
|
|
34113
|
+
return {
|
|
34114
|
+
success: false,
|
|
34115
|
+
error: "Request timed out. The AI agent is taking too long to respond. Please try again."
|
|
34116
|
+
};
|
|
34117
|
+
}
|
|
34118
|
+
return {
|
|
34119
|
+
success: false,
|
|
34120
|
+
error: errorMsg
|
|
34121
|
+
};
|
|
34122
|
+
}
|
|
34123
|
+
}
|
|
34124
|
+
/**
|
|
34125
|
+
* Check if Optifye Agent API is healthy
|
|
34126
|
+
*/
|
|
34127
|
+
async checkHealth() {
|
|
34128
|
+
try {
|
|
34129
|
+
const response = await fetch(`${this.apiUrl}/health`, {
|
|
34130
|
+
signal: AbortSignal.timeout(1e4)
|
|
34131
|
+
// 10 second timeout
|
|
34132
|
+
});
|
|
34133
|
+
if (response.ok) {
|
|
34134
|
+
const healthData = await response.json();
|
|
34135
|
+
return healthData.status === "healthy";
|
|
34136
|
+
}
|
|
34137
|
+
return false;
|
|
34138
|
+
} catch (error) {
|
|
34139
|
+
console.error("[OptifyeAgent] Health check failed:", error);
|
|
34140
|
+
return false;
|
|
34141
|
+
}
|
|
34142
|
+
}
|
|
34143
|
+
};
|
|
34144
|
+
var optifyeAgentClient = new OptifyeAgentClient();
|
|
34145
|
+
async function getManufacturingInsights(userQuestion, lineId, shiftId, companyId, context) {
|
|
34146
|
+
if (!userQuestion || !userQuestion.trim()) {
|
|
34147
|
+
return {
|
|
34148
|
+
success: false,
|
|
34149
|
+
error: "Please provide a question"
|
|
34150
|
+
};
|
|
34151
|
+
}
|
|
34152
|
+
if (!lineId || !companyId) {
|
|
34153
|
+
console.warn("[OptifyeAgent] Missing required IDs:", { lineId, companyId });
|
|
34154
|
+
}
|
|
34155
|
+
return optifyeAgentClient.getManufacturingInsights(
|
|
34156
|
+
userQuestion,
|
|
34157
|
+
lineId,
|
|
34158
|
+
shiftId,
|
|
34159
|
+
companyId,
|
|
34160
|
+
context
|
|
34161
|
+
);
|
|
34162
|
+
}
|
|
33521
34163
|
function createStreamProxyHandler(config) {
|
|
33522
|
-
const cloudFrontDomain = config?.cloudFrontDomain || "https://
|
|
34164
|
+
const cloudFrontDomain = config?.cloudFrontDomain || "https://d1eiob0chi5jw.cloudfront.net";
|
|
33523
34165
|
return async function handler(req, res) {
|
|
33524
34166
|
if (req.method !== "GET") {
|
|
33525
34167
|
return res.status(405).json({ error: "Method not allowed" });
|
|
@@ -33623,4 +34265,4 @@ lodash/lodash.js:
|
|
|
33623
34265
|
*)
|
|
33624
34266
|
*/
|
|
33625
34267
|
|
|
33626
|
-
export { ACTION_NAMES, AIAgentView_default as AIAgentView, AuthCallback, AuthCallbackView_default as AuthCallbackView, AuthProvider, AuthenticatedFactoryView, AuthenticatedHomeView, AuthenticatedTargetsView, BarChart, BaseHistoryCalendar, BottlenecksContent, 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_WORKSPACE_CONFIG, DEFAULT_WORKSPACE_POSITIONS, DashboardHeader, DashboardLayout, DashboardOverridesProvider, DashboardProvider, DateDisplay_default as DateDisplay, DateTimeDisplay, DebugAuth, DebugAuthView_default as DebugAuthView, EmptyStateMessage, FactoryView_default as FactoryView, GridComponentsPlaceholder, Header, HomeView_default as HomeView, HourlyOutputChart2 as HourlyOutputChart, ISTTimer_default as ISTTimer, KPICard, KPIDetailView_default as KPIDetailView, KPIGrid, KPIHeader, KPISection, LINE_1_UUID, LargeOutputProgressChart, LeaderboardDetailView_default as LeaderboardDetailView, LeaderboardIndexView_default as LeaderboardIndexView, Legend5 as Legend, LineChart, LineHistoryCalendar, LineMonthlyHistory, LineMonthlyPdfGenerator, LinePdfExportButton, LinePdfGenerator, LineWhatsAppShareButton, LiveTimer, LoadingOverlay_default as LoadingOverlay, LoadingPage_default as LoadingPage, LoadingSpinner_default as LoadingSpinner, LoginPage, LoginView_default as LoginView, MainLayout, MetricCard_default as MetricCard, NoWorkspaceData, OptifyeAgentClient, OutputProgressChart, PageHeader, ProfileView_default as ProfileView, RegistryProvider, S3Service, SOPComplianceChart, Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectScrollDownButton, SelectScrollUpButton, SelectSeparator, SelectTrigger, SelectValue, ShiftDisplay_default as ShiftDisplay, ShiftsView_default as ShiftsView, SideNavBar, SingleVideoStream_default as SingleVideoStream, Skeleton, SupabaseProvider, TargetWorkspaceGrid, TargetsView_default as TargetsView, TimeDisplay_default as TimeDisplay, VideoCard, VideoGridView, VideoPreloader, WORKSPACE_POSITIONS, WhatsAppShareButton, WorkspaceCard, WorkspaceDetailView_default as WorkspaceDetailView, WorkspaceGrid, WorkspaceGridItem, WorkspaceHistoryCalendar, WorkspaceMetricCards, WorkspaceMonthlyDataFetcher, WorkspaceMonthlyPdfGenerator, WorkspacePdfExportButton, WorkspacePdfGenerator, WorkspaceWhatsAppShareButton, actionService, apiUtils, authCoreService, authOTPService, authRateLimitService, checkRateLimit2 as checkRateLimit, clearAllRateLimits2 as clearAllRateLimits, clearRateLimit2 as clearRateLimit, clearS3VideoCache, clearS3VideoFromCache, clearWorkspaceDisplayNamesCache, cn, createStreamProxyHandler, createSupabaseClient, createThrottledReload, dashboardService, formatDateInZone, formatDateTimeInZone, formatISTDate, formatIdleTime, formatTimeInZone, fromUrlFriendlyName, getAllWorkspaceDisplayNamesAsync, getAnonClient, getCameraNumber, getCompanyMetricsTableName, getConfigurableShortWorkspaceDisplayName, getConfigurableWorkspaceDisplayName, getCurrentShift, getCurrentTimeInZone, getDashboardHeaderTimeInZone, getDaysDifferenceInZone, getDefaultCameraStreamUrl, getDefaultTabForWorkspace, getManufacturingInsights, getMetricsTablePrefix, getOperationalDate, getS3SignedUrl, getS3VideoSrc, getShortWorkspaceDisplayName, getShortWorkspaceDisplayNameAsync, getStoredWorkspaceMappings, getWorkspaceDisplayName, getWorkspaceDisplayNameAsync, getWorkspaceDisplayNamesMap, getWorkspaceFromUrl, getWorkspaceNavigationParams, identifyCoreUser, initializeCoreMixpanel, isTransitionPeriod, isValidLineInfoPayload, isValidWorkspaceDetailedMetricsPayload, isValidWorkspaceMetricsPayload, isWorkspaceDisplayNamesLoaded, isWorkspaceDisplayNamesLoading, mergeWithDefaultConfig, optifyeAgentClient, preloadS3Video, preloadS3VideoUrl, preloadS3VideosUrl, preloadVideoUrl, preloadVideosUrl, qualityService, realtimeService, refreshWorkspaceDisplayNames, resetCoreMixpanel, s3VideoPreloader, storeWorkspaceMapping, streamProxyConfig, throttledReloadDashboard, toUrlFriendlyName, trackCoreEvent, trackCorePageView, useAnalyticsConfig, useAuth, useAuthConfig, useComponentOverride, useCustomConfig, useDashboardConfig, useDashboardMetrics, useDatabaseConfig, useDateFormatter, useDateTimeConfig, useEndpointsConfig, useEntityConfig, useFactoryOverviewMetrics, useFeatureFlags, useFormatNumber, useHistoricWorkspaceMetrics, useHlsStream, useHookOverride, useLeaderboardMetrics, useLineDetailedMetrics, useLineKPIs, useLineMetrics, useLineWorkspaceMetrics, useMetrics, useNavigation, useOverrides, usePageOverride, useRealtimeLineMetrics, useRegistry, useShiftConfig, useShifts, useSupabase, useSupabaseClient, useTargets, useTheme, useThemeConfig, useWorkspaceConfig, useWorkspaceDetailedMetrics, useWorkspaceDisplayName, useWorkspaceDisplayNames, useWorkspaceDisplayNamesMap, useWorkspaceMetrics, useWorkspaceNavigation, useWorkspaceOperators, videoPreloader, whatsappService, withAuth, withRegistry, workspaceService };
|
|
34268
|
+
export { ACTION_NAMES, AIAgentView_default as AIAgentView, AuthCallback, AuthCallbackView_default as AuthCallbackView, AuthProvider, AuthenticatedFactoryView, AuthenticatedHomeView, AuthenticatedTargetsView, BarChart, BaseHistoryCalendar, BottlenecksContent, 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_WORKSPACE_CONFIG, DEFAULT_WORKSPACE_POSITIONS, DashboardHeader, DashboardLayout, DashboardOverridesProvider, DashboardProvider, DateDisplay_default as DateDisplay, DateTimeDisplay, DebugAuth, DebugAuthView_default as DebugAuthView, EmptyStateMessage, FactoryView_default as FactoryView, GridComponentsPlaceholder, Header, HomeView_default as HomeView, HourlyOutputChart2 as HourlyOutputChart, ISTTimer_default as ISTTimer, KPICard, KPIDetailView_default as KPIDetailView, KPIGrid, KPIHeader, KPISection, LINE_1_UUID, LargeOutputProgressChart, LeaderboardDetailView_default as LeaderboardDetailView, LeaderboardIndexView_default as LeaderboardIndexView, Legend5 as Legend, LineChart, LineHistoryCalendar, LineMonthlyHistory, LineMonthlyPdfGenerator, LinePdfExportButton, LinePdfGenerator, LineWhatsAppShareButton, LiveTimer, LoadingOverlay_default as LoadingOverlay, LoadingPage_default as LoadingPage, LoadingSpinner_default as LoadingSpinner, LoginPage, LoginView_default as LoginView, MainLayout, MetricCard_default as MetricCard, NoWorkspaceData, OptifyeAgentClient, OutputProgressChart, PageHeader, ProfileView_default as ProfileView, RegistryProvider, S3Service, 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, SupabaseProvider, TargetWorkspaceGrid, TargetsView_default as TargetsView, ThreadSidebar, TimeDisplay_default as TimeDisplay, VideoCard, VideoGridView, VideoPreloader, WORKSPACE_POSITIONS, WhatsAppShareButton, WorkspaceCard, WorkspaceDetailView_default as WorkspaceDetailView, WorkspaceGrid, WorkspaceGridItem, WorkspaceHistoryCalendar, WorkspaceMetricCards, WorkspaceMonthlyDataFetcher, WorkspaceMonthlyPdfGenerator, WorkspacePdfExportButton, WorkspacePdfGenerator, WorkspaceWhatsAppShareButton, actionService, apiUtils, authCoreService, authOTPService, authRateLimitService, checkRateLimit2 as checkRateLimit, clearAllRateLimits2 as clearAllRateLimits, clearRateLimit2 as clearRateLimit, clearS3VideoCache, clearS3VideoFromCache, clearWorkspaceDisplayNamesCache, cn, createStreamProxyHandler, createSupabaseClient, createThrottledReload, dashboardService, deleteThread, formatDateInZone, formatDateTimeInZone, formatISTDate, formatIdleTime, formatTimeInZone, fromUrlFriendlyName, getAllThreadMessages, getAllWorkspaceDisplayNamesAsync, getAnonClient, getCameraNumber, getCompanyMetricsTableName, getConfigurableShortWorkspaceDisplayName, getConfigurableWorkspaceDisplayName, getCurrentShift, getCurrentTimeInZone, getDashboardHeaderTimeInZone, getDaysDifferenceInZone, getDefaultCameraStreamUrl, getDefaultTabForWorkspace, getManufacturingInsights, getMetricsTablePrefix, getOperationalDate, getS3SignedUrl, getS3VideoSrc, getShortWorkspaceDisplayName, getShortWorkspaceDisplayNameAsync, getStoredWorkspaceMappings, getThreadMessages, getUserThreads, getUserThreadsPaginated, getWorkspaceDisplayName, getWorkspaceDisplayNameAsync, getWorkspaceDisplayNamesMap, getWorkspaceFromUrl, getWorkspaceNavigationParams, identifyCoreUser, initializeCoreMixpanel, isTransitionPeriod, isValidLineInfoPayload, isValidWorkspaceDetailedMetricsPayload, isValidWorkspaceMetricsPayload, isWorkspaceDisplayNamesLoaded, isWorkspaceDisplayNamesLoading, mergeWithDefaultConfig, optifyeAgentClient, preloadS3Video, preloadS3VideoUrl, preloadS3VideosUrl, preloadVideoUrl, preloadVideosUrl, qualityService, realtimeService, refreshWorkspaceDisplayNames, resetCoreMixpanel, s3VideoPreloader, storeWorkspaceMapping, streamProxyConfig, throttledReloadDashboard, toUrlFriendlyName, trackCoreEvent, trackCorePageView, updateThreadTitle, useAnalyticsConfig, useAuth, useAuthConfig, useComponentOverride, useCustomConfig, useDashboardConfig, useDashboardMetrics, useDatabaseConfig, useDateFormatter, useDateTimeConfig, useEndpointsConfig, useEntityConfig, useFactoryOverviewMetrics, useFeatureFlags, useFormatNumber, useHistoricWorkspaceMetrics, useHlsStream, useHookOverride, useLeaderboardMetrics, useLineDetailedMetrics, useLineKPIs, useLineMetrics, useLineWorkspaceMetrics, useMessages, useMetrics, useNavigation, useOverrides, usePageOverride, useRealtimeLineMetrics, useRegistry, useShiftConfig, useShifts, useSupabase, useSupabaseClient, useTargets, useTheme, useThemeConfig, useThreads, useWorkspaceConfig, useWorkspaceDetailedMetrics, useWorkspaceDisplayName, useWorkspaceDisplayNames, useWorkspaceDisplayNamesMap, useWorkspaceMetrics, useWorkspaceNavigation, useWorkspaceOperators, videoPreloader, whatsappService, withAuth, withRegistry, workspaceService };
|