@burdenoff/microfe-movethewheels 2026.716.2 → 2026.719.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1147,18 +1147,6 @@ export type GetMovethewheelsDashboardQuery = {
1147
1147
  }>;
1148
1148
  };
1149
1149
  };
1150
- export type GetAssistantInsightsQueryVariables = Types.Exact<{
1151
- question: Types.Scalars['String']['input'];
1152
- }>;
1153
- export type GetAssistantInsightsQuery = {
1154
- __typename?: 'Query';
1155
- assistantInsights: {
1156
- __typename?: 'AssistantInsights';
1157
- question: string;
1158
- answer: string;
1159
- generatedAt: string;
1160
- };
1161
- };
1162
1150
  export type ListCustomersQueryVariables = Types.Exact<{
1163
1151
  filter?: Types.InputMaybe<Types.CustomerFilterInput>;
1164
1152
  pagination?: Types.InputMaybe<Types.PaginationInput>;
@@ -2964,36 +2952,6 @@ export type GetMovethewheelsDashboardQueryHookResult = ReturnType<typeof useGetM
2964
2952
  export type GetMovethewheelsDashboardLazyQueryHookResult = ReturnType<typeof useGetMovethewheelsDashboardLazyQuery>;
2965
2953
  export type GetMovethewheelsDashboardSuspenseQueryHookResult = ReturnType<typeof useGetMovethewheelsDashboardSuspenseQuery>;
2966
2954
  export type GetMovethewheelsDashboardQueryResult = Apollo.QueryResult<Types.GetMovethewheelsDashboardQuery, Types.GetMovethewheelsDashboardQueryVariables>;
2967
- export declare const GetAssistantInsightsDocument: Apollo.DocumentNode;
2968
- /**
2969
- * __useGetAssistantInsightsQuery__
2970
- *
2971
- * To run a query within a React component, call `useGetAssistantInsightsQuery` and pass it any options that fit your needs.
2972
- * When your component renders, `useGetAssistantInsightsQuery` returns an object from Apollo Client that contains loading, error, and data properties
2973
- * you can use to render your UI.
2974
- *
2975
- * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;
2976
- *
2977
- * @example
2978
- * const { data, loading, error } = useGetAssistantInsightsQuery({
2979
- * variables: {
2980
- * question: // value for 'question'
2981
- * },
2982
- * });
2983
- */
2984
- export declare function useGetAssistantInsightsQuery(baseOptions: ApolloReactHooks.QueryHookOptions<Types.GetAssistantInsightsQuery, Types.GetAssistantInsightsQueryVariables> & ({
2985
- variables: Types.GetAssistantInsightsQueryVariables;
2986
- skip?: boolean;
2987
- } | {
2988
- skip: boolean;
2989
- })): ApolloReactHooks.useQuery.Result<Types.GetAssistantInsightsQuery, Types.GetAssistantInsightsQueryVariables, "empty" | "complete" | "streaming", Types.GetAssistantInsightsQueryVariables>;
2990
- export declare function useGetAssistantInsightsLazyQuery(baseOptions?: ApolloReactHooks.LazyQueryHookOptions<Types.GetAssistantInsightsQuery, Types.GetAssistantInsightsQueryVariables>): ApolloReactHooks.useLazyQuery.ResultTuple<Types.GetAssistantInsightsQuery, Types.GetAssistantInsightsQueryVariables, "empty" | "complete" | "streaming">;
2991
- export declare function useGetAssistantInsightsSuspenseQuery(baseOptions?: ApolloReactHooks.SuspenseQueryHookOptions<Types.GetAssistantInsightsQuery, Types.GetAssistantInsightsQueryVariables>): ApolloReactHooks.UseSuspenseQueryResult<Types.GetAssistantInsightsQuery, Types.GetAssistantInsightsQueryVariables>;
2992
- export declare function useGetAssistantInsightsSuspenseQuery(baseOptions?: ApolloReactHooks.SkipToken | ApolloReactHooks.SuspenseQueryHookOptions<Types.GetAssistantInsightsQuery, Types.GetAssistantInsightsQueryVariables>): ApolloReactHooks.UseSuspenseQueryResult<Types.GetAssistantInsightsQuery | undefined, Types.GetAssistantInsightsQueryVariables>;
2993
- export type GetAssistantInsightsQueryHookResult = ReturnType<typeof useGetAssistantInsightsQuery>;
2994
- export type GetAssistantInsightsLazyQueryHookResult = ReturnType<typeof useGetAssistantInsightsLazyQuery>;
2995
- export type GetAssistantInsightsSuspenseQueryHookResult = ReturnType<typeof useGetAssistantInsightsSuspenseQuery>;
2996
- export type GetAssistantInsightsQueryResult = Apollo.QueryResult<Types.GetAssistantInsightsQuery, Types.GetAssistantInsightsQueryVariables>;
2997
2955
  export declare const ListCustomersDocument: Apollo.DocumentNode;
2998
2956
  /**
2999
2957
  * __useListCustomersQuery__
@@ -5,7 +5,6 @@ import "./useCustomers.js";
5
5
  import "./useRoutes.js";
6
6
  import "./useAnalytics.js";
7
7
  import "./useTracking.js";
8
- import "./useAssistant.js";
9
8
  import "./useReports.js";
10
9
  import "./useImportExport.js";
11
10
  import "./useSettings.js";
package/dist/index.js CHANGED
@@ -9,31 +9,30 @@ import { useCustomer as b, useCustomerStats as x, useCustomers as S } from "./ho
9
9
  import { useRoute as C, useRouteStats as w, useRoutes as T } from "./hooks/useRoutes.js";
10
10
  import { useAnalytics as E, useDashboardMetrics as D, useFinanceMetrics as O, useFleetAnalytics as k, useOrderAnalytics as A, usePerformanceAnalytics as j, useRevenueAnalytics as M } from "./hooks/useAnalytics.js";
11
11
  import { useDriverTracking as N, useGeofence as P, useLiveTracking as F, useOrderTracking as I, useTracking as L, useTrackingAlerts as R, useVehicleTracking as z } from "./hooks/useTracking.js";
12
- import { useAssistant as B } from "./hooks/useAssistant.js";
13
- import { useReports as V } from "./hooks/useReports.js";
14
- import { useImportExport as H } from "./hooks/useImportExport.js";
15
- import { useModuleSettings as U } from "./hooks/useSettings.js";
16
- import { useEntityDocuments as W } from "./hooks/useEntityDocuments.js";
12
+ import { useReports as B } from "./hooks/useReports.js";
13
+ import { useImportExport as V } from "./hooks/useImportExport.js";
14
+ import { useModuleSettings as H } from "./hooks/useSettings.js";
15
+ import { useEntityDocuments as U } from "./hooks/useEntityDocuments.js";
17
16
  import "./hooks/index.js";
18
- import { Avatar as G, AvatarFallback as K, AvatarImage as q, Badge as J, Button as Y, Card as X, CardContent as Z, CardDescription as Q, CardFooter as $, CardHeader as ee, CardTitle as te, Checkbox as ne, Dialog as re, DialogContent as ie, DialogDescription as ae, DialogFooter as oe, DialogHeader as se, DialogTitle as ce, DialogTrigger as le, DropdownMenu as ue, DropdownMenuContent as de, DropdownMenuItem as fe, DropdownMenuSeparator as pe, DropdownMenuTrigger as me, Input as he, Label as ge, Progress as _e, ScrollArea as ve, Select as ye, SelectContent as be, SelectItem as xe, SelectTrigger as Se, SelectValue as Ce, Separator as we, Skeleton as Te, Switch as Ee, Table as De, TableBody as Oe, TableCell as ke, TableHead as Ae, TableHeader as je, TableRow as Me, Tabs as Ne, TabsContent as Pe, TabsList as Fe, TabsTrigger as Ie, Textarea as Le, Tooltip as Re, TooltipContent as ze, TooltipProvider as Be, TooltipTrigger as Ve } from "./components/ui.js";
19
- import { EmptyState as He, ErrorState as Ue, LoadingState as We, PageLayout as Ge, PageSection as Ke } from "./components/PageLayout.js";
20
- import { chartTokens as qe, seriesColor as Je } from "./components/charts/chartTokens.js";
21
- import { Sparkline as Ye } from "./components/charts/Sparkline.js";
22
- import { MetricCard as Xe, MetricCardSkeleton as Ze, MetricGrid as Qe } from "./components/MetricCard.js";
23
- import { GlassPanel as $e } from "./components/GlassPanel.js";
24
- import { ChartEmpty as et, ChartTooltip as tt } from "./components/charts/ChartShell.js";
25
- import { TrendChart as nt } from "./components/charts/TrendChart.js";
26
- import { VolumeBar as rt } from "./components/charts/VolumeBar.js";
27
- import { StatusDonut as it } from "./components/charts/StatusDonut.js";
28
- import { createCurrentIcon as at, createPinIcon as ot, createStopIcon as st, isRealCoord as ct } from "./components/maps/leaflet-setup.js";
29
- import { MapCanvas as lt } from "./components/maps/MapCanvas.js";
30
- import { LogisticsMap as ut } from "./components/maps/LogisticsMap.js";
31
- import { RouteMap as dt } from "./components/maps/RouteMap.js";
32
- import { TrackingMap as ft } from "./components/maps/TrackingMap.js";
33
- import { PaymentStatusBadge as pt, PriorityBadge as mt, StatusBadge as ht, TypeBadge as gt, VehicleTypeBadge as _t } from "./components/StatusBadge.js";
34
- import { DataTable as vt } from "./components/DataTable.js";
35
- import { FormError as yt } from "./components/FormError.js";
36
- import { Notice as bt, useNotice as xt } from "./components/Notice.js";
37
- import { DocumentsCard as St } from "./components/DocumentsCard.js";
17
+ import { Avatar as W, AvatarFallback as G, AvatarImage as K, Badge as q, Button as J, Card as Y, CardContent as X, CardDescription as Z, CardFooter as Q, CardHeader as $, CardTitle as ee, Checkbox as te, Dialog as ne, DialogContent as re, DialogDescription as ie, DialogFooter as ae, DialogHeader as oe, DialogTitle as se, DialogTrigger as ce, DropdownMenu as le, DropdownMenuContent as ue, DropdownMenuItem as de, DropdownMenuSeparator as fe, DropdownMenuTrigger as pe, Input as me, Label as he, Progress as ge, ScrollArea as _e, Select as ve, SelectContent as ye, SelectItem as be, SelectTrigger as xe, SelectValue as Se, Separator as Ce, Skeleton as we, Switch as Te, Table as Ee, TableBody as De, TableCell as Oe, TableHead as ke, TableHeader as Ae, TableRow as je, Tabs as Me, TabsContent as Ne, TabsList as Pe, TabsTrigger as Fe, Textarea as Ie, Tooltip as Le, TooltipContent as Re, TooltipProvider as ze, TooltipTrigger as Be } from "./components/ui.js";
18
+ import { EmptyState as Ve, ErrorState as He, LoadingState as Ue, PageLayout as We, PageSection as Ge } from "./components/PageLayout.js";
19
+ import { chartTokens as Ke, seriesColor as qe } from "./components/charts/chartTokens.js";
20
+ import { Sparkline as Je } from "./components/charts/Sparkline.js";
21
+ import { MetricCard as Ye, MetricCardSkeleton as Xe, MetricGrid as Ze } from "./components/MetricCard.js";
22
+ import { GlassPanel as Qe } from "./components/GlassPanel.js";
23
+ import { ChartEmpty as $e, ChartTooltip as et } from "./components/charts/ChartShell.js";
24
+ import { TrendChart as tt } from "./components/charts/TrendChart.js";
25
+ import { VolumeBar as nt } from "./components/charts/VolumeBar.js";
26
+ import { StatusDonut as rt } from "./components/charts/StatusDonut.js";
27
+ import { createCurrentIcon as it, createPinIcon as at, createStopIcon as ot, isRealCoord as st } from "./components/maps/leaflet-setup.js";
28
+ import { MapCanvas as ct } from "./components/maps/MapCanvas.js";
29
+ import { LogisticsMap as lt } from "./components/maps/LogisticsMap.js";
30
+ import { RouteMap as ut } from "./components/maps/RouteMap.js";
31
+ import { TrackingMap as dt } from "./components/maps/TrackingMap.js";
32
+ import { PaymentStatusBadge as ft, PriorityBadge as pt, StatusBadge as mt, TypeBadge as ht, VehicleTypeBadge as gt } from "./components/StatusBadge.js";
33
+ import { DataTable as _t } from "./components/DataTable.js";
34
+ import { FormError as vt } from "./components/FormError.js";
35
+ import { Notice as yt, useNotice as bt } from "./components/Notice.js";
36
+ import { DocumentsCard as xt } from "./components/DocumentsCard.js";
38
37
  import "./components/index.js";
39
- export { G as Avatar, K as AvatarFallback, q as AvatarImage, J as Badge, Y as Button, X as Card, Z as CardContent, Q as CardDescription, $ as CardFooter, ee as CardHeader, te as CardTitle, et as ChartEmpty, tt as ChartTooltip, ne as Checkbox, vt as DataTable, re as Dialog, ie as DialogContent, ae as DialogDescription, oe as DialogFooter, se as DialogHeader, ce as DialogTitle, le as DialogTrigger, St as DocumentsCard, ue as DropdownMenu, de as DropdownMenuContent, fe as DropdownMenuItem, pe as DropdownMenuSeparator, me as DropdownMenuTrigger, He as EmptyState, Ue as ErrorState, yt as FormError, $e as GlassPanel, he as Input, ge as Label, We as LoadingState, ut as LogisticsMap, lt as MapCanvas, Xe as MetricCard, Ze as MetricCardSkeleton, Qe as MetricGrid, n as MoveTheWheelsRoot, bt as Notice, Ge as PageLayout, Ke as PageSection, pt as PaymentStatusBadge, mt as PriorityBadge, _e as Progress, dt as RouteMap, ve as ScrollArea, ye as Select, be as SelectContent, xe as SelectItem, Se as SelectTrigger, Ce as SelectValue, we as Separator, Te as Skeleton, Ye as Sparkline, ht as StatusBadge, it as StatusDonut, Ee as Switch, De as Table, Oe as TableBody, ke as TableCell, Ae as TableHead, je as TableHeader, Me as TableRow, Ne as Tabs, Pe as TabsContent, Fe as TabsList, Ie as TabsTrigger, Le as Textarea, Re as Tooltip, ze as TooltipContent, Be as TooltipProvider, Ve as TooltipTrigger, ft as TrackingMap, nt as TrendChart, gt as TypeBadge, _t as VehicleTypeBadge, rt as VolumeBar, qe as chartTokens, at as createCurrentIcon, ot as createPinIcon, st as createStopIcon, ct as isRealCoord, Je as seriesColor, E as useAnalytics, B as useAssistant, b as useCustomer, x as useCustomerStats, S as useCustomers, D as useDashboardMetrics, c as useDriver, N as useDriverTracking, l as useDrivers, W as useEntityDocuments, O as useFinanceMetrics, u as useFleet, k as useFleetAnalytics, d as useFleetStats, P as useGeofence, H as useImportExport, m as useInventory, h as useInventoryStats, F as useLiveTracking, U as useModuleSettings, e as useMoveTheWheels, t as useMoveTheWheelsNavigate, r as useMoveTheWheelsStore, xt as useNotice, a as useOrder, A as useOrderAnalytics, o as useOrderStats, I as useOrderTracking, s as useOrders, j as usePerformanceAnalytics, g as useProduct, _ as useProducts, V as useReports, M as useRevenueAnalytics, C as useRoute, w as useRouteStats, T as useRoutes, i as useSandboxAssistantTransport, L as useTracking, R as useTrackingAlerts, f as useVehicle, z as useVehicleTracking, p as useVehicles, v as useWarehouse, y as useWarehouses };
38
+ export { W as Avatar, G as AvatarFallback, K as AvatarImage, q as Badge, J as Button, Y as Card, X as CardContent, Z as CardDescription, Q as CardFooter, $ as CardHeader, ee as CardTitle, $e as ChartEmpty, et as ChartTooltip, te as Checkbox, _t as DataTable, ne as Dialog, re as DialogContent, ie as DialogDescription, ae as DialogFooter, oe as DialogHeader, se as DialogTitle, ce as DialogTrigger, xt as DocumentsCard, le as DropdownMenu, ue as DropdownMenuContent, de as DropdownMenuItem, fe as DropdownMenuSeparator, pe as DropdownMenuTrigger, Ve as EmptyState, He as ErrorState, vt as FormError, Qe as GlassPanel, me as Input, he as Label, Ue as LoadingState, lt as LogisticsMap, ct as MapCanvas, Ye as MetricCard, Xe as MetricCardSkeleton, Ze as MetricGrid, n as MoveTheWheelsRoot, yt as Notice, We as PageLayout, Ge as PageSection, ft as PaymentStatusBadge, pt as PriorityBadge, ge as Progress, ut as RouteMap, _e as ScrollArea, ve as Select, ye as SelectContent, be as SelectItem, xe as SelectTrigger, Se as SelectValue, Ce as Separator, we as Skeleton, Je as Sparkline, mt as StatusBadge, rt as StatusDonut, Te as Switch, Ee as Table, De as TableBody, Oe as TableCell, ke as TableHead, Ae as TableHeader, je as TableRow, Me as Tabs, Ne as TabsContent, Pe as TabsList, Fe as TabsTrigger, Ie as Textarea, Le as Tooltip, Re as TooltipContent, ze as TooltipProvider, Be as TooltipTrigger, dt as TrackingMap, tt as TrendChart, ht as TypeBadge, gt as VehicleTypeBadge, nt as VolumeBar, Ke as chartTokens, it as createCurrentIcon, at as createPinIcon, ot as createStopIcon, st as isRealCoord, qe as seriesColor, E as useAnalytics, b as useCustomer, x as useCustomerStats, S as useCustomers, D as useDashboardMetrics, c as useDriver, N as useDriverTracking, l as useDrivers, U as useEntityDocuments, O as useFinanceMetrics, u as useFleet, k as useFleetAnalytics, d as useFleetStats, P as useGeofence, V as useImportExport, m as useInventory, h as useInventoryStats, F as useLiveTracking, H as useModuleSettings, e as useMoveTheWheels, t as useMoveTheWheelsNavigate, r as useMoveTheWheelsStore, bt as useNotice, a as useOrder, A as useOrderAnalytics, o as useOrderStats, I as useOrderTracking, s as useOrders, j as usePerformanceAnalytics, g as useProduct, _ as useProducts, B as useReports, M as useRevenueAnalytics, C as useRoute, w as useRouteStats, T as useRoutes, i as useSandboxAssistantTransport, L as useTracking, R as useTrackingAlerts, f as useVehicle, z as useVehicleTracking, p as useVehicles, v as useWarehouse, y as useWarehouses };
@@ -10,7 +10,6 @@ export { useCustomers, useCustomer, useCustomerStats } from './useCustomers';
10
10
  export { useRoutes, useRoute, useRouteStats } from './useRoutes';
11
11
  export { useAnalytics, useDashboardMetrics, useRevenueAnalytics, useOrderAnalytics, useFleetAnalytics, usePerformanceAnalytics, useFinanceMetrics, type FinanceMetrics, } from './useAnalytics';
12
12
  export { useTracking, useOrderTracking, useVehicleTracking, useDriverTracking, useLiveTracking, useTrackingAlerts, useGeofence, } from './useTracking';
13
- export { useAssistant } from './useAssistant';
14
13
  export { useReports } from './useReports';
15
14
  export { useImportExport } from './useImportExport';
16
15
  export { useModuleSettings } from './useSettings';
@@ -1,4 +1,22 @@
1
1
  /**
2
- * AI Assistant Page
2
+ * AI Operations Page
3
+ *
4
+ * This page previously shipped a second, fabricated chat surface
5
+ * (`useAssistant` → `Query.assistantInsights`) whose "capabilities" list
6
+ * advertised route optimization, demand forecasting, fleet analysis, cost
7
+ * optimization and natural-language queries — none of which the backend
8
+ * implemented; every question routed to a fixed template built from four
9
+ * Prisma counts. See BOFF-3897.
10
+ *
11
+ * The real conversational assistant is the shared `AssistantWidget`, already
12
+ * mounted globally in the app shell (`AppShell.tsx`) on the sandbox
13
+ * transport — this page must never contain a second chat box.
14
+ *
15
+ * The full "AI Operations" surface this page is meant to become — a model
16
+ * picker, an agent-activity feed reading the shared AgentRun ledger,
17
+ * accept/reject decision cards for AI dispatch proposals, and per-workspace
18
+ * AI credit visibility — depends on the shared multi-model AI gateway
19
+ * (BOFF-3601), which has not landed yet. Until it does, this page shows an
20
+ * honest roadmap state instead of fabricating any of that content.
3
21
  */
4
22
  export default function AIAssistantPage(): import("react").JSX.Element;
@@ -0,0 +1,8 @@
1
+ import { createLucideIcon as e } from "../createLucideIcon.js";
2
+ //#region node_modules/lucide-react/dist/esm/icons/message-circle.js
3
+ var t = e("MessageCircle", [["path", {
4
+ d: "M7.9 20A9 9 0 1 0 4 16.1L2 22Z",
5
+ key: "vv11sd"
6
+ }]]);
7
+ //#endregion
8
+ export { t as MessageCircle };
@@ -0,0 +1,11 @@
1
+ import { createLucideIcon as e } from "../createLucideIcon.js";
2
+ //#region node_modules/lucide-react/dist/esm/icons/shield-check.js
3
+ var t = e("ShieldCheck", [["path", {
4
+ d: "M20 13c0 5-3.5 7.5-7.66 8.95a1 1 0 0 1-.67-.01C7.5 20.5 4 18 4 13V6a1 1 0 0 1 1-1c2 0 4.5-1.2 6.24-2.72a1.17 1.17 0 0 1 1.52 0C14.51 3.81 17 5 19 5a1 1 0 0 1 1 1z",
5
+ key: "oel41y"
6
+ }], ["path", {
7
+ d: "m9 12 2 2 4-4",
8
+ key: "dzmm74"
9
+ }]]);
10
+ //#endregion
11
+ export { t as ShieldCheck };
@@ -0,0 +1,11 @@
1
+ import { createLucideIcon as e } from "../createLucideIcon.js";
2
+ //#region node_modules/lucide-react/dist/esm/icons/wallet.js
3
+ var t = e("Wallet", [["path", {
4
+ d: "M19 7V4a1 1 0 0 0-1-1H5a2 2 0 0 0 0 4h15a1 1 0 0 1 1 1v4h-3a2 2 0 0 0 0 4h3a1 1 0 0 0 1-1v-2a1 1 0 0 0-1-1",
5
+ key: "18etb6"
6
+ }], ["path", {
7
+ d: "M3 5v14a2 2 0 0 0 2 2h15a1 1 0 0 0 1-1v-4",
8
+ key: "xoc0q4"
9
+ }]]);
10
+ //#endregion
11
+ export { t as Wallet };
@@ -1,206 +1,79 @@
1
- import { Bot as e } from "../node_modules/lucide-react/dist/esm/icons/bot.js";
2
- import { CircleAlert as t } from "../node_modules/lucide-react/dist/esm/icons/circle-alert.js";
3
- import { Lightbulb as n } from "../node_modules/lucide-react/dist/esm/icons/lightbulb.js";
4
- import { Route as r } from "../node_modules/lucide-react/dist/esm/icons/route.js";
5
- import { Send as i } from "../node_modules/lucide-react/dist/esm/icons/send.js";
6
- import { Sparkles as a } from "../node_modules/lucide-react/dist/esm/icons/sparkles.js";
7
- import { TrendingUp as o } from "../node_modules/lucide-react/dist/esm/icons/trending-up.js";
8
- import { useAssistant as s } from "../hooks/useAssistant.js";
9
- import { Badge as c, Button as l, Card as u, CardContent as d, CardHeader as f, CardTitle as p, Input as m, ScrollArea as h } from "../components/ui.js";
10
- import { PageLayout as g } from "../components/PageLayout.js";
11
- import { useState as _ } from "react";
12
- import { jsx as v, jsxs as y } from "react/jsx-runtime";
13
- import { GlassCard as b, PagePurpose as x } from "@burdenoff/fe-libs/ui";
1
+ import { Activity as e } from "../node_modules/lucide-react/dist/esm/icons/activity.js";
2
+ import { Bot as t } from "../node_modules/lucide-react/dist/esm/icons/bot.js";
3
+ import { MessageCircle as n } from "../node_modules/lucide-react/dist/esm/icons/message-circle.js";
4
+ import { ShieldCheck as r } from "../node_modules/lucide-react/dist/esm/icons/shield-check.js";
5
+ import { Wallet as i } from "../node_modules/lucide-react/dist/esm/icons/wallet.js";
6
+ import { Card as a, CardContent as o, CardHeader as s, CardTitle as c } from "../components/ui.js";
7
+ import { EmptyState as l, PageLayout as u } from "../components/PageLayout.js";
8
+ import { jsx as d, jsxs as f } from "react/jsx-runtime";
9
+ import { GlassCard as p, PagePurpose as m } from "@burdenoff/fe-libs/ui";
14
10
  //#region src/movethewheels/pages/AIAssistantPage.tsx
15
- function S() {
16
- let { ask: S, isLoading: C } = s(), [w, T] = _(""), [E, D] = _([{
17
- role: "assistant",
18
- content: "Hello! I'm your logistics assistant. Ask me about your orders, deliveries, fleet or inventory and I'll answer from your live operational data."
19
- }]), O = [
20
- {
21
- icon: r,
22
- text: "Optimize today's delivery routes",
23
- category: "Route Planning"
24
- },
25
- {
26
- icon: o,
27
- text: "Show demand forecast for next week",
28
- category: "Analytics"
29
- },
30
- {
31
- icon: t,
32
- text: "Identify potential delivery delays",
33
- category: "Alerts"
34
- },
35
- {
36
- icon: n,
37
- text: "Suggest fleet efficiency improvements",
38
- category: "Insights"
39
- }
40
- ], k = [
41
- "Route Optimization - Find the most efficient delivery routes",
42
- "Demand Forecasting - Predict order volumes and trends",
43
- "Fleet Analysis - Insights on vehicle and driver performance",
44
- "Cost Optimization - Identify ways to reduce operational costs",
45
- "Natural Language Queries - Ask questions in plain English"
46
- ], A = async (e) => {
47
- let t = e.trim();
48
- if (!(!t || C)) {
49
- T(""), D((e) => [...e, {
50
- role: "user",
51
- content: t
52
- }]);
53
- try {
54
- let e = await S(t);
55
- D((t) => [...t, {
56
- role: "assistant",
57
- content: e.answer
58
- }]);
59
- } catch (e) {
60
- D((t) => [...t, {
61
- role: "assistant",
62
- content: e instanceof Error ? `Sorry, I couldn't answer that: ${e.message}` : "Sorry, I couldn't reach the assistant. Please try again.",
63
- isError: !0
64
- }]);
65
- }
66
- }
67
- }, j = () => {
68
- A(w);
69
- };
70
- return /* @__PURE__ */ y(g, {
71
- title: "AI Assistant",
72
- subtitle: "Intelligent logistics support",
73
- icon: /* @__PURE__ */ v(e, { size: 24 }),
74
- children: [/* @__PURE__ */ v(x, {
75
- icon: /* @__PURE__ */ v(e, { size: 18 }),
76
- children: "Ask plain-English questions about your operation and get answers backed by your own data. Use it to optimize routes, forecast demand, spot likely delays, and run what-if scenarios (e.g. “what if I add two vehicles?”) — like having a logistics analyst on call."
77
- }), /* @__PURE__ */ y("div", {
78
- className: "grid grid-cols-1 lg:grid-cols-3 gap-6",
79
- children: [/* @__PURE__ */ v("div", {
80
- className: "lg:col-span-2 space-y-4",
81
- children: /* @__PURE__ */ y(b, {
82
- treatment: "glass",
83
- glow: !0,
84
- className: "h-[600px] flex flex-col",
85
- children: [
86
- /* @__PURE__ */ v(f, {
87
- className: "border-b border-border-seam",
88
- children: /* @__PURE__ */ y(p, {
89
- className: "flex items-center gap-2",
90
- children: [/* @__PURE__ */ v(a, {
91
- size: 18,
92
- className: "text-primary"
93
- }), " Chat with AI"]
94
- })
95
- }),
96
- /* @__PURE__ */ v(h, {
97
- className: "flex-1 p-4",
98
- children: /* @__PURE__ */ y("div", {
99
- className: "space-y-4",
100
- children: [E.map((e, t) => /* @__PURE__ */ v("div", {
101
- className: `flex ${e.role === "user" ? "justify-end" : "justify-start"}`,
102
- children: /* @__PURE__ */ v("div", {
103
- className: `max-w-[80%] p-3 rounded-lg ${e.role === "user" ? "bg-action-primary-bg text-action-primary-text" : e.isError ? "bg-status-error-bg-subtle text-status-error-text" : "bg-bg-sunken"}`,
104
- children: /* @__PURE__ */ v("p", {
105
- className: "whitespace-pre-line text-sm",
106
- children: e.content
107
- })
108
- })
109
- }, t)), C && /* @__PURE__ */ v("div", {
110
- className: "flex justify-start",
111
- "aria-live": "polite",
112
- children: /* @__PURE__ */ y("div", {
113
- className: "max-w-[80%] p-3 rounded-lg bg-bg-sunken flex items-center gap-2",
114
- children: [/* @__PURE__ */ v(a, {
115
- size: 14,
116
- className: "text-primary motion-safe:animate-pulse"
117
- }), /* @__PURE__ */ v("span", {
118
- className: "text-sm text-text-secondary",
119
- children: "Analyzing your data…"
120
- })]
121
- })
122
- })]
123
- })
124
- }),
125
- /* @__PURE__ */ v("div", {
126
- className: "p-4 border-t",
127
- children: /* @__PURE__ */ y("div", {
128
- className: "flex gap-2",
129
- children: [/* @__PURE__ */ v(m, {
130
- value: w,
131
- onChange: (e) => T(e.target.value),
132
- placeholder: "Ask me anything about your logistics operations...",
133
- disabled: C,
134
- onKeyPress: (e) => e.key === "Enter" && j()
135
- }), /* @__PURE__ */ v(l, {
136
- onClick: j,
137
- disabled: C || !w.trim(),
138
- children: /* @__PURE__ */ v(i, { size: 16 })
139
- })]
140
- })
141
- })
142
- ]
11
+ var h = [
12
+ {
13
+ icon: e,
14
+ title: "Agent activity feed",
15
+ description: "A live log of what the AI decided, on which shipments, with trigger, model, latency and cost — so an autonomous run is never a black box."
16
+ },
17
+ {
18
+ icon: r,
19
+ title: "Dispatch decision cards",
20
+ description: "Proposed driver/vehicle assignments and carrier recommendations with rationale and confidence, requiring an explicit accept or reject before anything is written."
21
+ },
22
+ {
23
+ icon: i,
24
+ title: "AI credit visibility",
25
+ description: "Per-workspace AI spend for admins, so cost is visible before the invoice."
26
+ }
27
+ ];
28
+ function g() {
29
+ return /* @__PURE__ */ f(u, {
30
+ title: "AI Operations",
31
+ subtitle: "What the AI is doing on your workspace, and why",
32
+ icon: /* @__PURE__ */ d(t, { size: 24 }),
33
+ children: [
34
+ /* @__PURE__ */ d(m, {
35
+ icon: /* @__PURE__ */ d(t, { size: 18 }),
36
+ children: "This page will surface AI-driven dispatch decisions and their outcomes once the shared AI runtime lands. It does not host a chat box — chat with your live operational data is always available from the assistant icon anywhere in the app."
37
+ }),
38
+ /* @__PURE__ */ d(p, {
39
+ treatment: "glass",
40
+ className: "p-4",
41
+ children: /* @__PURE__ */ f("div", {
42
+ className: "flex items-start gap-3",
43
+ children: [/* @__PURE__ */ d(n, {
44
+ size: 20,
45
+ className: "text-primary flex-shrink-0 mt-0.5"
46
+ }), /* @__PURE__ */ f("div", { children: [/* @__PURE__ */ d("p", {
47
+ className: "text-sm font-medium text-text-primary",
48
+ children: "Looking to ask a question about your operations?"
49
+ }), /* @__PURE__ */ d("p", {
50
+ className: "text-sm text-text-secondary mt-1",
51
+ children: "Open the assistant from its icon in the corner of the screen — it answers from your live orders, shipments, fleet and inventory data, and it is the only chat surface in this product."
52
+ })] })]
143
53
  })
144
- }), /* @__PURE__ */ y("div", {
145
- className: "space-y-6",
146
- children: [
147
- /* @__PURE__ */ y(u, { children: [/* @__PURE__ */ v(f, { children: /* @__PURE__ */ v(p, { children: "Quick Actions" }) }), /* @__PURE__ */ v(d, {
148
- className: "space-y-2",
149
- children: O.map((e, t) => /* @__PURE__ */ y(l, {
150
- variant: "outline",
151
- className: "w-full justify-start text-left h-auto py-3",
152
- disabled: C,
153
- onClick: () => void A(e.text),
154
- children: [
155
- /* @__PURE__ */ v(e.icon, {
156
- size: 16,
157
- className: "mr-2 flex-shrink-0"
158
- }),
159
- /* @__PURE__ */ v("span", {
160
- className: "flex-1",
161
- children: e.text
162
- }),
163
- /* @__PURE__ */ v(c, {
164
- variant: "secondary",
165
- className: "text-xs",
166
- children: e.category
167
- })
168
- ]
169
- }, t))
170
- })] }),
171
- /* @__PURE__ */ y(u, { children: [/* @__PURE__ */ v(f, { children: /* @__PURE__ */ v(p, { children: "Capabilities" }) }), /* @__PURE__ */ v(d, { children: /* @__PURE__ */ v("ul", {
172
- className: "space-y-2 text-sm",
173
- children: k.map((e, t) => /* @__PURE__ */ y("li", {
174
- className: "flex items-start gap-2",
175
- children: [/* @__PURE__ */ v(a, {
176
- size: 14,
177
- className: "text-primary mt-0.5 flex-shrink-0"
178
- }), /* @__PURE__ */ v("span", { children: e })]
179
- }, t))
180
- }) })] }),
181
- /* @__PURE__ */ v(u, {
182
- className: "bg-action-primary-bg/5 border-primary/20",
183
- children: /* @__PURE__ */ v(d, {
184
- className: "p-4",
185
- children: /* @__PURE__ */ y("div", {
186
- className: "flex items-start gap-3",
187
- children: [/* @__PURE__ */ v(n, {
188
- size: 20,
189
- className: "text-primary flex-shrink-0"
190
- }), /* @__PURE__ */ y("div", { children: [/* @__PURE__ */ v("p", {
191
- className: "font-medium text-sm",
192
- children: "Pro Tip"
193
- }), /* @__PURE__ */ v("p", {
194
- className: "text-xs text-text-secondary",
195
- children: "You can ask complex questions like \"What would happen if I added 2 more vehicles to my fleet?\" for scenario analysis."
196
- })] })]
197
- })
198
- })
199
- })
200
- ]
201
- })]
202
- })]
54
+ }),
55
+ /* @__PURE__ */ f(a, { children: [/* @__PURE__ */ d(s, { children: /* @__PURE__ */ d(c, { children: "On the roadmap" }) }), /* @__PURE__ */ f(o, { children: [/* @__PURE__ */ d(l, {
56
+ illustration: "empty-agents",
57
+ title: "Autonomous dispatch operations aren't live yet",
58
+ description: "These capabilities depend on the shared multi-model AI gateway and agent-run ledger (BOFF-3601), which hasn't shipped across the platform yet. Nothing below is available today."
59
+ }), /* @__PURE__ */ d("ul", {
60
+ className: "mt-4 space-y-4",
61
+ children: h.map((e) => /* @__PURE__ */ f("li", {
62
+ className: "flex items-start gap-3",
63
+ children: [/* @__PURE__ */ d(e.icon, {
64
+ size: 18,
65
+ className: "text-text-secondary flex-shrink-0 mt-0.5"
66
+ }), /* @__PURE__ */ f("div", { children: [/* @__PURE__ */ d("p", {
67
+ className: "text-sm font-medium text-text-primary",
68
+ children: e.title
69
+ }), /* @__PURE__ */ d("p", {
70
+ className: "text-xs text-text-secondary",
71
+ children: e.description
72
+ })] })]
73
+ }, e.title))
74
+ })] })] })
75
+ ]
203
76
  });
204
77
  }
205
78
  //#endregion
206
- export { S as default };
79
+ export { g as default };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@burdenoff/microfe-movethewheels",
3
- "version": "2026.716.2",
3
+ "version": "2026.719.1",
4
4
  "description": "Burdenoff MoveTheWheels Microfrontend - Logistics & Supply Chain Management Platform",
5
5
  "type": "module",
6
6
  "files": [
@@ -387,13 +387,6 @@ export type GetMovethewheelsDashboardQueryVariables = Types.Exact<{ [key: string
387
387
 
388
388
  export type GetMovethewheelsDashboardQuery = { __typename?: 'Query', dashboardMetrics: { __typename?: 'DashboardMetrics', totalOrders: number, activeDeliveries: number, availableDrivers: number, activeVehicles: number, lowStockItems: number, totalRevenue: number, recentOrders: Array<{ __typename?: 'MovethewheelsOrder', id: string, orderNumber: string, orderType: Types.OrderType, status: Types.OrderStatus, priority: Types.OrderPriority, customerId: string, trackingNumber?: string | null, pickupAddress: Record<string, unknown>, deliveryAddress: Record<string, unknown>, items: Record<string, unknown>, pricing?: Record<string, unknown> | null, scheduledDelivery?: string | null, vehicleId?: string | null, driverId?: string | null, createdAt: string, updatedAt: string }> }, orderStats: { __typename?: 'OrderStats', total: number, pending: number, inTransit: number, delivered: number, cancelled: number, failed: number }, fleetStats: { __typename?: 'FleetStats', totalVehicles: number, activeVehicles: number, inTransitVehicles: number, maintenanceVehicles: number, totalDrivers: number, availableDrivers: number, onDeliveryDrivers: number }, financeMetrics: { __typename?: 'FinanceMetrics', fuelCost: number, openInvoices: number, revenue: { __typename?: 'RevenueMetrics', totalRevenue: number, averageOrderValue: number, deliveredRevenue: number } }, analytics: { __typename?: 'AnalyticsSeries', deliveryTrend: Array<{ __typename?: 'AnalyticsPoint', label: string, value: number }>, orderTrend: Array<{ __typename?: 'AnalyticsPoint', label: string, value: number }>, revenueTrend: Array<{ __typename?: 'AnalyticsPoint', label: string, value: number }> } };
389
389
 
390
- export type GetAssistantInsightsQueryVariables = Types.Exact<{
391
- question: Types.Scalars['String']['input'];
392
- }>;
393
-
394
-
395
- export type GetAssistantInsightsQuery = { __typename?: 'Query', assistantInsights: { __typename?: 'AssistantInsights', question: string, answer: string, generatedAt: string } };
396
-
397
390
  export type ListCustomersQueryVariables = Types.Exact<{
398
391
  filter?: Types.InputMaybe<Types.CustomerFilterInput>;
399
392
  pagination?: Types.InputMaybe<Types.PaginationInput>;
@@ -2466,51 +2459,6 @@ export type GetMovethewheelsDashboardQueryHookResult = ReturnType<typeof useGetM
2466
2459
  export type GetMovethewheelsDashboardLazyQueryHookResult = ReturnType<typeof useGetMovethewheelsDashboardLazyQuery>;
2467
2460
  export type GetMovethewheelsDashboardSuspenseQueryHookResult = ReturnType<typeof useGetMovethewheelsDashboardSuspenseQuery>;
2468
2461
  export type GetMovethewheelsDashboardQueryResult = Apollo.QueryResult<Types.GetMovethewheelsDashboardQuery, Types.GetMovethewheelsDashboardQueryVariables>;
2469
- export const GetAssistantInsightsDocument = gql`
2470
- query GetAssistantInsights($question: String!) {
2471
- assistantInsights(question: $question) {
2472
- question
2473
- answer
2474
- generatedAt
2475
- }
2476
- }
2477
- `;
2478
-
2479
- /**
2480
- * __useGetAssistantInsightsQuery__
2481
- *
2482
- * To run a query within a React component, call `useGetAssistantInsightsQuery` and pass it any options that fit your needs.
2483
- * When your component renders, `useGetAssistantInsightsQuery` returns an object from Apollo Client that contains loading, error, and data properties
2484
- * you can use to render your UI.
2485
- *
2486
- * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;
2487
- *
2488
- * @example
2489
- * const { data, loading, error } = useGetAssistantInsightsQuery({
2490
- * variables: {
2491
- * question: // value for 'question'
2492
- * },
2493
- * });
2494
- */
2495
- export function useGetAssistantInsightsQuery(baseOptions: ApolloReactHooks.QueryHookOptions<Types.GetAssistantInsightsQuery, Types.GetAssistantInsightsQueryVariables> & ({ variables: Types.GetAssistantInsightsQueryVariables; skip?: boolean; } | { skip: boolean; }) ) {
2496
- const options = {...defaultOptions, ...baseOptions}
2497
- return ApolloReactHooks.useQuery<Types.GetAssistantInsightsQuery, Types.GetAssistantInsightsQueryVariables>(GetAssistantInsightsDocument, options);
2498
- }
2499
- export function useGetAssistantInsightsLazyQuery(baseOptions?: ApolloReactHooks.LazyQueryHookOptions<Types.GetAssistantInsightsQuery, Types.GetAssistantInsightsQueryVariables>) {
2500
- const options = {...defaultOptions, ...baseOptions}
2501
- return ApolloReactHooks.useLazyQuery<Types.GetAssistantInsightsQuery, Types.GetAssistantInsightsQueryVariables>(GetAssistantInsightsDocument, options);
2502
- }
2503
- // @ts-ignore
2504
- export function useGetAssistantInsightsSuspenseQuery(baseOptions?: ApolloReactHooks.SuspenseQueryHookOptions<Types.GetAssistantInsightsQuery, Types.GetAssistantInsightsQueryVariables>): ApolloReactHooks.UseSuspenseQueryResult<Types.GetAssistantInsightsQuery, Types.GetAssistantInsightsQueryVariables>;
2505
- export function useGetAssistantInsightsSuspenseQuery(baseOptions?: ApolloReactHooks.SkipToken | ApolloReactHooks.SuspenseQueryHookOptions<Types.GetAssistantInsightsQuery, Types.GetAssistantInsightsQueryVariables>): ApolloReactHooks.UseSuspenseQueryResult<Types.GetAssistantInsightsQuery | undefined, Types.GetAssistantInsightsQueryVariables>;
2506
- export function useGetAssistantInsightsSuspenseQuery(baseOptions?: ApolloReactHooks.SkipToken | ApolloReactHooks.SuspenseQueryHookOptions<Types.GetAssistantInsightsQuery, Types.GetAssistantInsightsQueryVariables>) {
2507
- const options = baseOptions === ApolloReactHooks.skipToken ? baseOptions : {...defaultOptions, ...baseOptions}
2508
- return ApolloReactHooks.useSuspenseQuery<Types.GetAssistantInsightsQuery, Types.GetAssistantInsightsQueryVariables>(GetAssistantInsightsDocument, options);
2509
- }
2510
- export type GetAssistantInsightsQueryHookResult = ReturnType<typeof useGetAssistantInsightsQuery>;
2511
- export type GetAssistantInsightsLazyQueryHookResult = ReturnType<typeof useGetAssistantInsightsLazyQuery>;
2512
- export type GetAssistantInsightsSuspenseQueryHookResult = ReturnType<typeof useGetAssistantInsightsSuspenseQuery>;
2513
- export type GetAssistantInsightsQueryResult = Apollo.QueryResult<Types.GetAssistantInsightsQuery, Types.GetAssistantInsightsQueryVariables>;
2514
2462
  export const ListCustomersDocument = gql`
2515
2463
  query ListCustomers($filter: CustomerFilterInput, $pagination: PaginationInput) {
2516
2464
  customers(filter: $filter, pagination: $pagination) {
@@ -56,9 +56,6 @@ export {
56
56
  useGeofence,
57
57
  } from './useTracking';
58
58
 
59
- // Assistant
60
- export { useAssistant } from './useAssistant';
61
-
62
59
  // Reports
63
60
  export { useReports } from './useReports';
64
61
 
@@ -61,7 +61,7 @@ export type {
61
61
  export { useMoveTheWheels, useMoveTheWheelsNavigate } from './providers/MoveTheWheelsProvider';
62
62
  export { useMoveTheWheelsStore } from './store/movethewheelsStore';
63
63
 
64
- // Transport adapter for the shared fe-libs AssistantWidget (workspace assistantInsights query).
64
+ // Transport adapter for the shared fe-libs AssistantWidget.
65
65
  // Consumers import it from the dedicated subpath
66
66
  // `@burdenoff/microfe-movethewheels/services/createSandboxAssistantTransport`
67
67
  // (see package.json exports) — that path has a clean, self-contained `.d.ts`.
@@ -1,206 +1,102 @@
1
1
  /**
2
- * AI Assistant Page
2
+ * AI Operations Page
3
+ *
4
+ * This page previously shipped a second, fabricated chat surface
5
+ * (`useAssistant` → `Query.assistantInsights`) whose "capabilities" list
6
+ * advertised route optimization, demand forecasting, fleet analysis, cost
7
+ * optimization and natural-language queries — none of which the backend
8
+ * implemented; every question routed to a fixed template built from four
9
+ * Prisma counts. See BOFF-3897.
10
+ *
11
+ * The real conversational assistant is the shared `AssistantWidget`, already
12
+ * mounted globally in the app shell (`AppShell.tsx`) on the sandbox
13
+ * transport — this page must never contain a second chat box.
14
+ *
15
+ * The full "AI Operations" surface this page is meant to become — a model
16
+ * picker, an agent-activity feed reading the shared AgentRun ledger,
17
+ * accept/reject decision cards for AI dispatch proposals, and per-workspace
18
+ * AI credit visibility — depends on the shared multi-model AI gateway
19
+ * (BOFF-3601), which has not landed yet. Until it does, this page shows an
20
+ * honest roadmap state instead of fabricating any of that content.
3
21
  */
4
22
 
5
- import { useState } from 'react';
6
- import { Bot, Send, Sparkles, Lightbulb, TrendingUp, Route, AlertCircle } from 'lucide-react';
7
- import { PageLayout } from '../components/PageLayout';
8
- import {
9
- Card,
10
- CardContent,
11
- CardHeader,
12
- CardTitle,
13
- Button,
14
- Input,
15
- Badge,
16
- ScrollArea,
17
- } from '../components/ui';
23
+ import { Bot, MessageCircle, Activity, ShieldCheck, Wallet } from 'lucide-react';
24
+ import { PageLayout, EmptyState } from '../components/PageLayout';
25
+ import { Card, CardContent, CardHeader, CardTitle } from '../components/ui';
18
26
  import { GlassCard, PagePurpose } from '@burdenoff/fe-libs/ui';
19
- import { useAssistant } from '../hooks/useAssistant';
20
27
 
21
- interface ChatMessage {
22
- role: 'assistant' | 'user';
23
- content: string;
24
- isError?: boolean;
25
- }
28
+ const roadmapItems = [
29
+ {
30
+ icon: Activity,
31
+ title: 'Agent activity feed',
32
+ description:
33
+ 'A live log of what the AI decided, on which shipments, with trigger, model, latency and cost — so an autonomous run is never a black box.',
34
+ },
35
+ {
36
+ icon: ShieldCheck,
37
+ title: 'Dispatch decision cards',
38
+ description:
39
+ 'Proposed driver/vehicle assignments and carrier recommendations with rationale and confidence, requiring an explicit accept or reject before anything is written.',
40
+ },
41
+ {
42
+ icon: Wallet,
43
+ title: 'AI credit visibility',
44
+ description: 'Per-workspace AI spend for admins, so cost is visible before the invoice.',
45
+ },
46
+ ];
26
47
 
27
48
  export default function AIAssistantPage() {
28
- const { ask, isLoading } = useAssistant();
29
- const [message, setMessage] = useState('');
30
- const [messages, setMessages] = useState<ChatMessage[]>([
31
- {
32
- role: 'assistant',
33
- content:
34
- "Hello! I'm your logistics assistant. Ask me about your orders, deliveries, fleet or inventory and I'll answer from your live operational data.",
35
- },
36
- ]);
37
-
38
- const suggestions = [
39
- { icon: Route, text: "Optimize today's delivery routes", category: 'Route Planning' },
40
- { icon: TrendingUp, text: 'Show demand forecast for next week', category: 'Analytics' },
41
- { icon: AlertCircle, text: 'Identify potential delivery delays', category: 'Alerts' },
42
- { icon: Lightbulb, text: 'Suggest fleet efficiency improvements', category: 'Insights' },
43
- ];
44
-
45
- const capabilities = [
46
- 'Route Optimization - Find the most efficient delivery routes',
47
- 'Demand Forecasting - Predict order volumes and trends',
48
- 'Fleet Analysis - Insights on vehicle and driver performance',
49
- 'Cost Optimization - Identify ways to reduce operational costs',
50
- 'Natural Language Queries - Ask questions in plain English',
51
- ];
52
-
53
- const submit = async (question: string) => {
54
- const trimmed = question.trim();
55
- if (!trimmed || isLoading) return;
56
- setMessage('');
57
- setMessages((previous) => [...previous, { role: 'user', content: trimmed }]);
58
- try {
59
- const result = await ask(trimmed);
60
- setMessages((previous) => [...previous, { role: 'assistant', content: result.answer }]);
61
- } catch (fetchError) {
62
- setMessages((previous) => [
63
- ...previous,
64
- {
65
- role: 'assistant',
66
- content:
67
- fetchError instanceof Error
68
- ? `Sorry, I couldn't answer that: ${fetchError.message}`
69
- : "Sorry, I couldn't reach the assistant. Please try again.",
70
- isError: true,
71
- },
72
- ]);
73
- }
74
- };
75
-
76
- const handleSend = () => {
77
- void submit(message);
78
- };
79
-
80
49
  return (
81
50
  <PageLayout
82
- title="AI Assistant"
83
- subtitle="Intelligent logistics support"
51
+ title="AI Operations"
52
+ subtitle="What the AI is doing on your workspace, and why"
84
53
  icon={<Bot size={24} />}
85
54
  >
86
55
  <PagePurpose icon={<Bot size={18} />}>
87
- Ask plain-English questions about your operation and get answers backed by your own data.
88
- Use it to optimize routes, forecast demand, spot likely delays, and run what-if scenarios
89
- (e.g. &ldquo;what if I add two vehicles?&rdquo;) — like having a logistics analyst on call.
56
+ This page will surface AI-driven dispatch decisions and their outcomes once the shared AI
57
+ runtime lands. It does not host a chat box — chat with your live operational data is always
58
+ available from the assistant icon anywhere in the app.
90
59
  </PagePurpose>
91
60
 
92
- <div className="grid grid-cols-1 lg:grid-cols-3 gap-6">
93
- <div className="lg:col-span-2 space-y-4">
94
- {/* Chat — the page's single emphasis zone */}
95
- <GlassCard treatment="glass" glow className="h-[600px] flex flex-col">
96
- <CardHeader className="border-b border-border-seam">
97
- <CardTitle className="flex items-center gap-2">
98
- <Sparkles size={18} className="text-primary" /> Chat with AI
99
- </CardTitle>
100
- </CardHeader>
101
- <ScrollArea className="flex-1 p-4">
102
- <div className="space-y-4">
103
- {messages.map((msg, i) => (
104
- <div
105
- key={i}
106
- className={`flex ${msg.role === 'user' ? 'justify-end' : 'justify-start'}`}
107
- >
108
- <div
109
- className={`max-w-[80%] p-3 rounded-lg ${
110
- msg.role === 'user'
111
- ? 'bg-action-primary-bg text-action-primary-text'
112
- : msg.isError
113
- ? 'bg-status-error-bg-subtle text-status-error-text'
114
- : 'bg-bg-sunken'
115
- }`}
116
- >
117
- <p className="whitespace-pre-line text-sm">{msg.content}</p>
118
- </div>
119
- </div>
120
- ))}
121
- {isLoading && (
122
- <div className="flex justify-start" aria-live="polite">
123
- <div className="max-w-[80%] p-3 rounded-lg bg-bg-sunken flex items-center gap-2">
124
- <Sparkles size={14} className="text-primary motion-safe:animate-pulse" />
125
- <span className="text-sm text-text-secondary">Analyzing your data…</span>
126
- </div>
127
- </div>
128
- )}
129
- </div>
130
- </ScrollArea>
131
- <div className="p-4 border-t">
132
- <div className="flex gap-2">
133
- <Input
134
- value={message}
135
- onChange={(e) => setMessage(e.target.value)}
136
- placeholder="Ask me anything about your logistics operations..."
137
- disabled={isLoading}
138
- onKeyPress={(e) => e.key === 'Enter' && handleSend()}
139
- />
140
- <Button onClick={handleSend} disabled={isLoading || !message.trim()}>
141
- <Send size={16} />
142
- </Button>
143
- </div>
144
- </div>
145
- </GlassCard>
61
+ <GlassCard treatment="glass" className="p-4">
62
+ <div className="flex items-start gap-3">
63
+ <MessageCircle size={20} className="text-primary flex-shrink-0 mt-0.5" />
64
+ <div>
65
+ <p className="text-sm font-medium text-text-primary">
66
+ Looking to ask a question about your operations?
67
+ </p>
68
+ <p className="text-sm text-text-secondary mt-1">
69
+ Open the assistant from its icon in the corner of the screen — it answers from your
70
+ live orders, shipments, fleet and inventory data, and it is the only chat surface in
71
+ this product.
72
+ </p>
73
+ </div>
146
74
  </div>
75
+ </GlassCard>
147
76
 
148
- <div className="space-y-6">
149
- <Card>
150
- <CardHeader>
151
- <CardTitle>Quick Actions</CardTitle>
152
- </CardHeader>
153
- <CardContent className="space-y-2">
154
- {suggestions.map((s, i) => (
155
- <Button
156
- key={i}
157
- variant="outline"
158
- className="w-full justify-start text-left h-auto py-3"
159
- disabled={isLoading}
160
- onClick={() => void submit(s.text)}
161
- >
162
- <s.icon size={16} className="mr-2 flex-shrink-0" />
163
- <span className="flex-1">{s.text}</span>
164
- <Badge variant="secondary" className="text-xs">
165
- {s.category}
166
- </Badge>
167
- </Button>
168
- ))}
169
- </CardContent>
170
- </Card>
171
-
172
- <Card>
173
- <CardHeader>
174
- <CardTitle>Capabilities</CardTitle>
175
- </CardHeader>
176
- <CardContent>
177
- <ul className="space-y-2 text-sm">
178
- {capabilities.map((cap, i) => (
179
- <li key={i} className="flex items-start gap-2">
180
- <Sparkles size={14} className="text-primary mt-0.5 flex-shrink-0" />
181
- <span>{cap}</span>
182
- </li>
183
- ))}
184
- </ul>
185
- </CardContent>
186
- </Card>
187
-
188
- <Card className="bg-action-primary-bg/5 border-primary/20">
189
- <CardContent className="p-4">
190
- <div className="flex items-start gap-3">
191
- <Lightbulb size={20} className="text-primary flex-shrink-0" />
77
+ <Card>
78
+ <CardHeader>
79
+ <CardTitle>On the roadmap</CardTitle>
80
+ </CardHeader>
81
+ <CardContent>
82
+ <EmptyState
83
+ illustration="empty-agents"
84
+ title="Autonomous dispatch operations aren't live yet"
85
+ description="These capabilities depend on the shared multi-model AI gateway and agent-run ledger (BOFF-3601), which hasn't shipped across the platform yet. Nothing below is available today."
86
+ />
87
+ <ul className="mt-4 space-y-4">
88
+ {roadmapItems.map((item) => (
89
+ <li key={item.title} className="flex items-start gap-3">
90
+ <item.icon size={18} className="text-text-secondary flex-shrink-0 mt-0.5" />
192
91
  <div>
193
- <p className="font-medium text-sm">Pro Tip</p>
194
- <p className="text-xs text-text-secondary">
195
- You can ask complex questions like "What would happen if I added 2 more vehicles
196
- to my fleet?" for scenario analysis.
197
- </p>
92
+ <p className="text-sm font-medium text-text-primary">{item.title}</p>
93
+ <p className="text-xs text-text-secondary">{item.description}</p>
198
94
  </div>
199
- </div>
200
- </CardContent>
201
- </Card>
202
- </div>
203
- </div>
95
+ </li>
96
+ ))}
97
+ </ul>
98
+ </CardContent>
99
+ </Card>
204
100
  </PageLayout>
205
101
  );
206
102
  }
@@ -51,11 +51,3 @@ query GetMovethewheelsDashboard {
51
51
  }
52
52
  }
53
53
  }
54
-
55
- query GetAssistantInsights($question: String!) {
56
- assistantInsights(question: $question) {
57
- question
58
- answer
59
- generatedAt
60
- }
61
- }
@@ -1,39 +0,0 @@
1
- import { useMoveTheWheels as e } from "../providers/MoveTheWheelsProvider.js";
2
- import { executeGraphQL as t } from "../utils/graphqlClient.js";
3
- import { useCallback as n, useMemo as r, useState as i } from "react";
4
- //#region src/movethewheels/hooks/useAssistant.ts
5
- var a = "\n query MovethewheelsAssistantInsights($question: String!) {\n assistantInsights(question: $question) {\n answer\n generatedAt\n question\n }\n }\n";
6
- function o() {
7
- let { apiGatewayUrl: o, authToken: s, workspaceToken: c, workspaceId: l, tenantId: u, currentUser: d } = e(), [f, p] = i(!1), [m, h] = i(null), g = r(() => ({
8
- apiGatewayUrl: o,
9
- authToken: s,
10
- workspaceToken: c,
11
- workspaceId: l,
12
- tenantId: u,
13
- actorId: d?.id
14
- }), [
15
- o,
16
- s,
17
- c,
18
- l,
19
- u,
20
- d?.id
21
- ]);
22
- return {
23
- ask: n(async (e) => {
24
- p(!0), h(null);
25
- try {
26
- return (await t(g, a, { question: e })).assistantInsights;
27
- } catch (e) {
28
- let t = e instanceof Error ? e : /* @__PURE__ */ Error("Failed to get assistant response");
29
- throw h(t), t;
30
- } finally {
31
- p(!1);
32
- }
33
- }, [g]),
34
- isLoading: f,
35
- error: m
36
- };
37
- }
38
- //#endregion
39
- export { o as useAssistant };
@@ -1,17 +0,0 @@
1
- export interface AssistantAnswer {
2
- answer: string;
3
- generatedAt: string;
4
- question: string;
5
- }
6
- interface UseAssistantResult {
7
- ask: (question: string) => Promise<AssistantAnswer>;
8
- isLoading: boolean;
9
- error: Error | null;
10
- }
11
- /**
12
- * useAssistant — queries the real logistics assistant (Query.assistantInsights).
13
- * The backend answers from the caller's own operational data; there is no
14
- * client-side canned response.
15
- */
16
- export declare function useAssistant(): UseAssistantResult;
17
- export {};
@@ -1,18 +0,0 @@
1
- import { createLucideIcon as e } from "../createLucideIcon.js";
2
- //#region node_modules/lucide-react/dist/esm/icons/lightbulb.js
3
- var t = e("Lightbulb", [
4
- ["path", {
5
- d: "M15 14c.2-1 .7-1.7 1.5-2.5 1-.9 1.5-2.2 1.5-3.5A6 6 0 0 0 6 8c0 1 .2 2.2 1.5 3.5.7.7 1.3 1.5 1.5 2.5",
6
- key: "1gvzjb"
7
- }],
8
- ["path", {
9
- d: "M9 18h6",
10
- key: "x1upvd"
11
- }],
12
- ["path", {
13
- d: "M10 22h4",
14
- key: "ceow96"
15
- }]
16
- ]);
17
- //#endregion
18
- export { t as Lightbulb };
@@ -1,11 +0,0 @@
1
- import { createLucideIcon as e } from "../createLucideIcon.js";
2
- //#region node_modules/lucide-react/dist/esm/icons/send.js
3
- var t = e("Send", [["path", {
4
- d: "M14.536 21.686a.5.5 0 0 0 .937-.024l6.5-19a.496.496 0 0 0-.635-.635l-19 6.5a.5.5 0 0 0-.024.937l7.93 3.18a2 2 0 0 1 1.112 1.11z",
5
- key: "1ffxy3"
6
- }], ["path", {
7
- d: "m21.854 2.147-10.94 10.939",
8
- key: "12cjpa"
9
- }]]);
10
- //#endregion
11
- export { t as Send };
@@ -1,26 +0,0 @@
1
- import { createLucideIcon as e } from "../createLucideIcon.js";
2
- //#region node_modules/lucide-react/dist/esm/icons/sparkles.js
3
- var t = e("Sparkles", [
4
- ["path", {
5
- d: "M9.937 15.5A2 2 0 0 0 8.5 14.063l-6.135-1.582a.5.5 0 0 1 0-.962L8.5 9.936A2 2 0 0 0 9.937 8.5l1.582-6.135a.5.5 0 0 1 .963 0L14.063 8.5A2 2 0 0 0 15.5 9.937l6.135 1.581a.5.5 0 0 1 0 .964L15.5 14.063a2 2 0 0 0-1.437 1.437l-1.582 6.135a.5.5 0 0 1-.963 0z",
6
- key: "4pj2yx"
7
- }],
8
- ["path", {
9
- d: "M20 3v4",
10
- key: "1olli1"
11
- }],
12
- ["path", {
13
- d: "M22 5h-4",
14
- key: "1gvqau"
15
- }],
16
- ["path", {
17
- d: "M4 17v2",
18
- key: "vumght"
19
- }],
20
- ["path", {
21
- d: "M5 18H3",
22
- key: "zchphs"
23
- }]
24
- ]);
25
- //#endregion
26
- export { t as Sparkles };
@@ -1,74 +0,0 @@
1
- import { useCallback, useMemo, useState } from 'react';
2
- import { useMoveTheWheels } from '../providers/MoveTheWheelsProvider';
3
- import { executeGraphQL } from '../utils/graphqlClient';
4
-
5
- export interface AssistantAnswer {
6
- answer: string;
7
- generatedAt: string;
8
- question: string;
9
- }
10
-
11
- const ASSISTANT_INSIGHTS_QUERY = `
12
- query MovethewheelsAssistantInsights($question: String!) {
13
- assistantInsights(question: $question) {
14
- answer
15
- generatedAt
16
- question
17
- }
18
- }
19
- `;
20
-
21
- interface UseAssistantResult {
22
- ask: (question: string) => Promise<AssistantAnswer>;
23
- isLoading: boolean;
24
- error: Error | null;
25
- }
26
-
27
- /**
28
- * useAssistant — queries the real logistics assistant (Query.assistantInsights).
29
- * The backend answers from the caller's own operational data; there is no
30
- * client-side canned response.
31
- */
32
- export function useAssistant(): UseAssistantResult {
33
- const { apiGatewayUrl, authToken, workspaceToken, workspaceId, tenantId, currentUser } =
34
- useMoveTheWheels();
35
- const [isLoading, setIsLoading] = useState(false);
36
- const [error, setError] = useState<Error | null>(null);
37
-
38
- const graphQLOptions = useMemo(
39
- () => ({
40
- apiGatewayUrl,
41
- authToken,
42
- workspaceToken,
43
- workspaceId,
44
- tenantId,
45
- actorId: currentUser?.id,
46
- }),
47
- [apiGatewayUrl, authToken, workspaceToken, workspaceId, tenantId, currentUser?.id]
48
- );
49
-
50
- const ask = useCallback(
51
- async (question: string): Promise<AssistantAnswer> => {
52
- setIsLoading(true);
53
- setError(null);
54
- try {
55
- const data = await executeGraphQL<{ assistantInsights: AssistantAnswer }>(
56
- graphQLOptions,
57
- ASSISTANT_INSIGHTS_QUERY,
58
- { question }
59
- );
60
- return data.assistantInsights;
61
- } catch (fetchError) {
62
- const normalized =
63
- fetchError instanceof Error ? fetchError : new Error('Failed to get assistant response');
64
- setError(normalized);
65
- throw normalized;
66
- } finally {
67
- setIsLoading(false);
68
- }
69
- },
70
- [graphQLOptions]
71
- );
72
-
73
- return { ask, isLoading, error };
74
- }