@agent-native/dispatch 0.40.0 → 0.40.2
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/CHANGELOG.md +38 -12
- package/dist/actions/provider-api-register.d.ts +7 -7
- package/dist/components/app-open-actions.d.ts +1 -1
- package/dist/components/app-open-actions.d.ts.map +1 -1
- package/dist/components/app-open-actions.js +1 -1
- package/dist/components/app-open-actions.js.map +1 -1
- package/dist/components/app-row-settings.js +1 -1
- package/dist/components/app-row-settings.js.map +1 -1
- package/dist/components/automation-create-dialog.js +2 -2
- package/dist/components/automation-create-dialog.js.map +1 -1
- package/dist/components/automation-details-panel.js +1 -1
- package/dist/components/automation-details-panel.js.map +1 -1
- package/dist/components/chat-home-apps.js +1 -1
- package/dist/components/chat-home-apps.js.map +1 -1
- package/dist/components/create-app-popover.js +3 -3
- package/dist/components/create-app-popover.js.map +1 -1
- package/dist/components/dispatch-control-plane.d.ts.map +1 -1
- package/dist/components/dispatch-control-plane.js +9 -30
- package/dist/components/dispatch-control-plane.js.map +1 -1
- package/dist/components/layout/Header.js +2 -2
- package/dist/components/layout/Header.js.map +1 -1
- package/dist/components/layout/Layout.d.ts +6 -5
- package/dist/components/layout/Layout.d.ts.map +1 -1
- package/dist/components/layout/Layout.js +73 -113
- package/dist/components/layout/Layout.js.map +1 -1
- package/dist/components/layout/workspace-apps-rail.d.ts.map +1 -1
- package/dist/components/layout/workspace-apps-rail.js +7 -19
- package/dist/components/layout/workspace-apps-rail.js.map +1 -1
- package/dist/components/messaging-setup-panel.js +2 -1
- package/dist/components/messaging-setup-panel.js.map +1 -1
- package/dist/components/workspace-app-card.js +2 -2
- package/dist/components/workspace-app-card.js.map +1 -1
- package/dist/components/workspace-app-host.d.ts +1 -1
- package/dist/components/workspace-app-host.d.ts.map +1 -1
- package/dist/components/workspace-app-host.js +7 -74
- package/dist/components/workspace-app-host.js.map +1 -1
- package/dist/hooks/use-navigation-state.js +1 -1
- package/dist/hooks/use-navigation-state.js.map +1 -1
- package/dist/lib/workspace-apps.js +1 -1
- package/dist/lib/workspace-apps.js.map +1 -1
- package/dist/routes/pages/$appId.js +1 -1
- package/dist/routes/pages/$appId.js.map +1 -1
- package/dist/routes/pages/_index.js +1 -1
- package/dist/routes/pages/_index.js.map +1 -1
- package/dist/routes/pages/admin._index.js +1 -1
- package/dist/routes/pages/admin._index.js.map +1 -1
- package/dist/routes/pages/agent-integrations.js +1 -1
- package/dist/routes/pages/agent-integrations.js.map +1 -1
- package/dist/routes/pages/apps.d.ts.map +1 -1
- package/dist/routes/pages/apps.js +3 -43
- package/dist/routes/pages/apps.js.map +1 -1
- package/dist/routes/pages/browser-chat.js +1 -1
- package/dist/routes/pages/browser-chat.js.map +1 -1
- package/dist/routes/pages/chat.d.ts.map +1 -1
- package/dist/routes/pages/chat.js +24 -43
- package/dist/routes/pages/chat.js.map +1 -1
- package/dist/routes/pages/extensions.$id.js +1 -1
- package/dist/routes/pages/extensions.$id.js.map +1 -1
- package/dist/routes/pages/extensions._index.js +1 -1
- package/dist/routes/pages/extensions._index.js.map +1 -1
- package/dist/routes/pages/integrations.js +1 -1
- package/dist/routes/pages/integrations.js.map +1 -1
- package/dist/routes/pages/new-app.js +1 -1
- package/dist/routes/pages/new-app.js.map +1 -1
- package/dist/routes/pages/operations.js +2 -2
- package/dist/routes/pages/operations.js.map +1 -1
- package/dist/routes/pages/overview.d.ts +2 -2
- package/dist/routes/pages/settings.d.ts.map +1 -1
- package/dist/routes/pages/settings.js +26 -8
- package/dist/routes/pages/settings.js.map +1 -1
- package/dist/routes/pages/tools.$id.js +1 -1
- package/dist/routes/pages/tools.$id.js.map +1 -1
- package/dist/routes/pages/tools._index.js +1 -1
- package/dist/routes/pages/tools._index.js.map +1 -1
- package/dist/routes/pages/vault.d.ts +1 -1
- package/dist/routes/pages/vault.js +1 -1
- package/dist/routes/pages/vault.js.map +1 -1
- package/dist/shared/app-roles.js.map +1 -1
- package/package.json +3 -3
- package/src/components/app-open-actions.tsx +1 -1
- package/src/components/app-row-settings.tsx +1 -1
- package/src/components/automation-create-dialog.tsx +7 -7
- package/src/components/automation-details-panel.tsx +1 -1
- package/src/components/chat-home-apps.tsx +1 -1
- package/src/components/create-app-popover.spec.tsx +5 -7
- package/src/components/create-app-popover.tsx +3 -3
- package/src/components/dispatch-control-plane.spec.tsx +12 -19
- package/src/components/dispatch-control-plane.tsx +10 -84
- package/src/components/layout/Header.tsx +2 -2
- package/src/components/layout/Layout.app-chat.spec.ts +1 -0
- package/src/components/layout/Layout.spec.tsx +18 -20
- package/src/components/layout/Layout.tsx +153 -205
- package/src/components/layout/workspace-apps-rail.spec.tsx +79 -0
- package/src/components/layout/workspace-apps-rail.tsx +6 -30
- package/src/components/messaging-setup-panel.tsx +1 -1
- package/src/components/workspace-app-card.tsx +2 -2
- package/src/components/workspace-app-chat-rail.spec.tsx +1 -1
- package/src/components/workspace-app-host.spec.tsx +19 -19
- package/src/components/workspace-app-host.tsx +12 -129
- package/src/hooks/use-navigation-state.ts +1 -1
- package/src/lib/workspace-apps.ts +1 -1
- package/src/routes/pages/$appId.tsx +1 -1
- package/src/routes/pages/_index.tsx +1 -1
- package/src/routes/pages/admin._index.tsx +1 -1
- package/src/routes/pages/agent-integrations.tsx +1 -1
- package/src/routes/pages/apps.tsx +2 -86
- package/src/routes/pages/automations.spec.tsx +1 -1
- package/src/routes/pages/browser-chat.tsx +1 -1
- package/src/routes/pages/chat.spec.tsx +23 -46
- package/src/routes/pages/chat.tsx +20 -57
- package/src/routes/pages/extensions.$id.tsx +1 -1
- package/src/routes/pages/extensions._index.tsx +1 -1
- package/src/routes/pages/integrations.tsx +1 -1
- package/src/routes/pages/new-app.tsx +1 -1
- package/src/routes/pages/operations.tsx +2 -2
- package/src/routes/pages/settings.spec.tsx +30 -8
- package/src/routes/pages/settings.tsx +75 -7
- package/src/routes/pages/tools.$id.tsx +1 -1
- package/src/routes/pages/tools._index.tsx +1 -1
- package/src/routes/pages/vault.tsx +1 -1
- package/src/shared/app-roles.ts +1 -1
|
@@ -1,14 +1,9 @@
|
|
|
1
1
|
import {
|
|
2
2
|
CHAT_FIRST_MODE_CHANGED_EVENT,
|
|
3
|
-
AgentChatSurface,
|
|
4
|
-
AgentToggleButton,
|
|
5
3
|
chatFirstSurfaceTabId,
|
|
6
|
-
AgentSidebar,
|
|
7
|
-
ChatFirstSurfacePanelToggle,
|
|
8
4
|
closeChatFirstSessionWatch,
|
|
9
5
|
emitChatFirstSessionWatch,
|
|
10
6
|
getChatFirstSurfaceTabsStore,
|
|
11
|
-
focusAgentChat,
|
|
12
7
|
navigateWithAgentChatViewTransition,
|
|
13
8
|
readChatFirstAppLayout,
|
|
14
9
|
readChatFirstMode,
|
|
@@ -39,6 +34,20 @@ import {
|
|
|
39
34
|
readClientAppState,
|
|
40
35
|
writeClientAppState,
|
|
41
36
|
} from "@agent-native/core/client/application-state";
|
|
37
|
+
import {
|
|
38
|
+
useFeatureFlagState,
|
|
39
|
+
type FeatureFlagState,
|
|
40
|
+
} from "@agent-native/core/client/feature-flags";
|
|
41
|
+
import { useActionQuery } from "@agent-native/core/client/hooks";
|
|
42
|
+
import { useT } from "@agent-native/core/client/i18n";
|
|
43
|
+
import { SETTINGS_REDESIGN_FLAG } from "@agent-native/core/feature-flags/registry";
|
|
44
|
+
import {
|
|
45
|
+
AgentChatSurface,
|
|
46
|
+
AgentToggleButton,
|
|
47
|
+
AgentSidebar,
|
|
48
|
+
focusAgentChat,
|
|
49
|
+
} from "@agent-native/toolkit/app/chat";
|
|
50
|
+
import { ChatFirstSurfacePanelToggle } from "@agent-native/toolkit/app/chat/chat-first";
|
|
42
51
|
import {
|
|
43
52
|
ChatFirstAgentsPane,
|
|
44
53
|
ChatFirstAppPane,
|
|
@@ -56,23 +65,21 @@ import {
|
|
|
56
65
|
type ChatFirstCopy,
|
|
57
66
|
type ChatFirstEmbedTarget,
|
|
58
67
|
type ChatFirstPrimaryTab,
|
|
59
|
-
} from "@agent-native/
|
|
60
|
-
import {
|
|
61
|
-
import {
|
|
62
|
-
import {
|
|
63
|
-
import {
|
|
64
|
-
import { InvitationBanner, OrgSwitcher } from "@agent-native/core/client/org";
|
|
65
|
-
import { RunsTray } from "@agent-native/core/client/progress";
|
|
66
|
-
import { isSettingsPathname } from "@agent-native/core/client/settings";
|
|
68
|
+
} from "@agent-native/toolkit/app/chat/chat-first";
|
|
69
|
+
import { FeedbackButton } from "@agent-native/toolkit/app/feedback";
|
|
70
|
+
import { InvitationBanner, OrgSwitcher } from "@agent-native/toolkit/app/org";
|
|
71
|
+
import { RunsTray } from "@agent-native/toolkit/app/progress";
|
|
72
|
+
import { isSettingsPathname } from "@agent-native/toolkit/app/settings";
|
|
67
73
|
import {
|
|
68
74
|
AppSidebarFooter,
|
|
69
75
|
AppSidebarHeader,
|
|
70
|
-
|
|
71
|
-
} from "@agent-native/
|
|
76
|
+
openCommandMenu,
|
|
77
|
+
} from "@agent-native/toolkit/app/shared";
|
|
72
78
|
import {
|
|
73
79
|
ChatHistoryRail,
|
|
74
80
|
type ChatHistoryItem,
|
|
75
81
|
} from "@agent-native/toolkit/chat-history";
|
|
82
|
+
import { writeClipboardText } from "@agent-native/toolkit/clipboard";
|
|
76
83
|
import {
|
|
77
84
|
IconApps,
|
|
78
85
|
IconBrandSlack,
|
|
@@ -113,8 +120,6 @@ import {
|
|
|
113
120
|
isPathMountedWorkspaceApp,
|
|
114
121
|
isWorkspaceAppVisibleInDefaultLaunchers,
|
|
115
122
|
isWorkspaceSsoApp,
|
|
116
|
-
mergeChatFirstWorkspaceApps,
|
|
117
|
-
workspaceAppSourceFromConnected,
|
|
118
123
|
navigateToWorkspaceApp,
|
|
119
124
|
shouldOpenWorkspaceAppInTopWindow,
|
|
120
125
|
workspaceAppIdFromRoute,
|
|
@@ -261,15 +266,6 @@ interface DispatchChatFirstPane {
|
|
|
261
266
|
view?: string;
|
|
262
267
|
}
|
|
263
268
|
|
|
264
|
-
interface ChatFirstConnectedAppSummary {
|
|
265
|
-
id: string;
|
|
266
|
-
name: string;
|
|
267
|
-
description?: string | null;
|
|
268
|
-
url?: string | null;
|
|
269
|
-
homeUrl?: string | null;
|
|
270
|
-
source?: string;
|
|
271
|
-
}
|
|
272
|
-
|
|
273
269
|
interface DispatchAgentThreadSummary {
|
|
274
270
|
id: string;
|
|
275
271
|
title: string;
|
|
@@ -286,7 +282,6 @@ const DispatchExtensionsContext = createContext<
|
|
|
286
282
|
DispatchExtensionConfig | undefined
|
|
287
283
|
>(undefined);
|
|
288
284
|
interface DispatchWorkspaceAppLauncher {
|
|
289
|
-
apps: readonly ChatFirstAppItem[];
|
|
290
285
|
workspaceApps: readonly WorkspaceAppSummary[];
|
|
291
286
|
isLoading: boolean;
|
|
292
287
|
error?: unknown;
|
|
@@ -361,11 +356,18 @@ export function shouldQueryChatFirstApps(
|
|
|
361
356
|
}
|
|
362
357
|
|
|
363
358
|
/**
|
|
364
|
-
* Settings brings its own navigation, header, and agent
|
|
365
|
-
* full width.
|
|
359
|
+
* The redesigned Settings brings its own navigation, header, and agent
|
|
360
|
+
* toggle, so it renders full width. While the flag loads it shows the
|
|
361
|
+
* shell's skeleton, which needs the same frame.
|
|
366
362
|
*/
|
|
367
|
-
export function
|
|
368
|
-
|
|
363
|
+
export function isRedesignedSettingsPath(
|
|
364
|
+
pathname: string,
|
|
365
|
+
settingsRedesign: FeatureFlagState,
|
|
366
|
+
): boolean {
|
|
367
|
+
return (
|
|
368
|
+
isSettingsPathname(localDispatchPath(pathname)) &&
|
|
369
|
+
(settingsRedesign.enabled || settingsRedesign.status === "loading")
|
|
370
|
+
);
|
|
369
371
|
}
|
|
370
372
|
|
|
371
373
|
function chatFirstPrimaryTabForPath(
|
|
@@ -1391,7 +1393,10 @@ export function Layout({
|
|
|
1391
1393
|
);
|
|
1392
1394
|
const isChatRoute =
|
|
1393
1395
|
localPathname === "/chat" || localPathname.startsWith("/chat/");
|
|
1394
|
-
const
|
|
1396
|
+
const isRedesignedSettingsRoute = isRedesignedSettingsPath(
|
|
1397
|
+
location.pathname,
|
|
1398
|
+
useFeatureFlagState(SETTINGS_REDESIGN_FLAG.key),
|
|
1399
|
+
);
|
|
1395
1400
|
const chatFirstSurfaceScope = threadIdFromPath(localPathname) ?? "new";
|
|
1396
1401
|
const isWorkspaceAppRoute = shouldAutoCollapseDispatchSidebar(
|
|
1397
1402
|
location.pathname,
|
|
@@ -1432,94 +1437,43 @@ export function Layout({
|
|
|
1432
1437
|
const chatFirstAppsQuery = useActionQuery<WorkspaceAppSummary[]>(
|
|
1433
1438
|
"list-workspace-apps",
|
|
1434
1439
|
{ includeAgentCards: false, includeArchived: true },
|
|
1435
|
-
{
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
|
|
1439
|
-
|
|
1440
|
-
ChatFirstConnectedAppSummary[]
|
|
1441
|
-
>(
|
|
1442
|
-
"list-connected-agents",
|
|
1443
|
-
{},
|
|
1444
|
-
{ enabled: shouldQueryChatFirstApps(isChatRoute, chatFirstMode) },
|
|
1445
|
-
);
|
|
1446
|
-
const chatFirstEnabledBuiltinAppIds = useMemo(
|
|
1447
|
-
() =>
|
|
1448
|
-
chatFirstConnectedAppsQuery.data
|
|
1449
|
-
?.filter((app) => app.source === "builtin")
|
|
1450
|
-
.map((app) => app.id),
|
|
1451
|
-
[chatFirstConnectedAppsQuery.data],
|
|
1440
|
+
{
|
|
1441
|
+
enabled:
|
|
1442
|
+
shouldQueryChatFirstApps(isChatRoute, chatFirstMode) ||
|
|
1443
|
+
workspaceAppRouteActive,
|
|
1444
|
+
},
|
|
1452
1445
|
);
|
|
1453
1446
|
const chatFirstWorkspaceApps = useMemo(
|
|
1454
1447
|
() =>
|
|
1455
|
-
|
|
1456
|
-
chatFirstAppsQuery.data,
|
|
1457
|
-
chatFirstEnabledBuiltinAppIds,
|
|
1458
|
-
),
|
|
1459
|
-
[chatFirstAppsQuery.data, chatFirstEnabledBuiltinAppIds],
|
|
1460
|
-
);
|
|
1461
|
-
const chatHomeWorkspaceApps = useMemo(
|
|
1462
|
-
() =>
|
|
1463
|
-
mergeChatFirstWorkspaceApps(
|
|
1464
|
-
chatFirstWorkspaceApps,
|
|
1465
|
-
chatFirstEnabledBuiltinAppIds,
|
|
1466
|
-
chatFirstConnectedAppsQuery.data?.map((app) => ({
|
|
1467
|
-
id: app.id,
|
|
1468
|
-
name: app.name,
|
|
1469
|
-
description: app.description,
|
|
1470
|
-
url: app.homeUrl?.trim() || app.url,
|
|
1471
|
-
source: workspaceAppSourceFromConnected(app.source),
|
|
1472
|
-
})),
|
|
1473
|
-
).filter(
|
|
1448
|
+
(chatFirstAppsQuery.data ?? []).filter(
|
|
1474
1449
|
(app) =>
|
|
1475
1450
|
app.status !== "pending" &&
|
|
1476
1451
|
app.archived !== true &&
|
|
1477
1452
|
isWorkspaceAppVisibleInDefaultLaunchers(app),
|
|
1478
1453
|
),
|
|
1479
|
-
[
|
|
1480
|
-
chatFirstConnectedAppsQuery.data,
|
|
1481
|
-
chatFirstEnabledBuiltinAppIds,
|
|
1482
|
-
chatFirstWorkspaceApps,
|
|
1483
|
-
],
|
|
1454
|
+
[chatFirstAppsQuery.data],
|
|
1484
1455
|
);
|
|
1485
1456
|
const chatFirstAppRegistrations = useMemo<ChatFirstAppRegistration[]>(() => {
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
|
|
1457
|
+
return (chatFirstAppsQuery.data ?? [])
|
|
1458
|
+
.filter((app) => app.status !== "pending" && app.archived !== true)
|
|
1459
|
+
.map((app) => ({
|
|
1489
1460
|
id: app.id,
|
|
1490
1461
|
name: app.name,
|
|
1491
|
-
source: app.source,
|
|
1462
|
+
source: app.source ?? "workspace",
|
|
1492
1463
|
path: app.path,
|
|
1493
1464
|
url: app.url,
|
|
1494
1465
|
homePath: app.homePath,
|
|
1495
|
-
enabled: app.status !== "pending" && app.archived !== true,
|
|
1496
|
-
});
|
|
1497
|
-
}
|
|
1498
|
-
for (const app of chatFirstConnectedAppsQuery.data ?? []) {
|
|
1499
|
-
const id = app.id.trim().toLowerCase();
|
|
1500
|
-
if (!id || registrations.has(id)) continue;
|
|
1501
|
-
registrations.set(id, {
|
|
1502
|
-
id,
|
|
1503
|
-
name: app.name,
|
|
1504
|
-
source: workspaceAppSourceFromConnected(app.source),
|
|
1505
|
-
url: app.homeUrl?.trim() || app.url,
|
|
1506
1466
|
enabled: true,
|
|
1507
|
-
});
|
|
1508
|
-
|
|
1509
|
-
return [...registrations.values()];
|
|
1510
|
-
}, [chatFirstConnectedAppsQuery.data, chatFirstWorkspaceApps]);
|
|
1467
|
+
}));
|
|
1468
|
+
}, [chatFirstAppsQuery.data]);
|
|
1511
1469
|
const chatFirstAppItems = useMemo<ChatFirstAppItem[]>(
|
|
1512
1470
|
() =>
|
|
1513
|
-
|
|
1514
|
-
.
|
|
1515
|
-
|
|
1516
|
-
|
|
1517
|
-
|
|
1518
|
-
|
|
1519
|
-
name: app.name ?? app.id,
|
|
1520
|
-
source: app.source,
|
|
1521
|
-
})),
|
|
1522
|
-
[chatFirstAppRegistrations],
|
|
1471
|
+
chatFirstWorkspaceApps.map((app) => ({
|
|
1472
|
+
id: app.id,
|
|
1473
|
+
name: app.name,
|
|
1474
|
+
source: app.source ?? "workspace",
|
|
1475
|
+
})),
|
|
1476
|
+
[chatFirstWorkspaceApps],
|
|
1523
1477
|
);
|
|
1524
1478
|
const openChatFirstApp = useCallback(
|
|
1525
1479
|
(app: ChatFirstAppItem) => {
|
|
@@ -1553,32 +1507,18 @@ export function Layout({
|
|
|
1553
1507
|
);
|
|
1554
1508
|
const chatHomeAppLauncher = useMemo<DispatchWorkspaceAppLauncher>(
|
|
1555
1509
|
() => ({
|
|
1556
|
-
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
chatFirstAppsQuery.isLoading || chatFirstConnectedAppsQuery.isLoading,
|
|
1560
|
-
error: chatFirstAppsQuery.isError
|
|
1561
|
-
? chatFirstAppsQuery.error
|
|
1562
|
-
: chatFirstConnectedAppsQuery.isError
|
|
1563
|
-
? chatFirstConnectedAppsQuery.error
|
|
1564
|
-
: undefined,
|
|
1510
|
+
workspaceApps: chatFirstWorkspaceApps,
|
|
1511
|
+
isLoading: chatFirstAppsQuery.isLoading,
|
|
1512
|
+
error: chatFirstAppsQuery.isError ? chatFirstAppsQuery.error : undefined,
|
|
1565
1513
|
openApp: openChatFirstApp,
|
|
1566
|
-
retry: () =>
|
|
1567
|
-
void chatFirstAppsQuery.refetch();
|
|
1568
|
-
void chatFirstConnectedAppsQuery.refetch();
|
|
1569
|
-
},
|
|
1514
|
+
retry: () => void chatFirstAppsQuery.refetch(),
|
|
1570
1515
|
}),
|
|
1571
1516
|
[
|
|
1572
1517
|
chatFirstAppsQuery.error,
|
|
1573
1518
|
chatFirstAppsQuery.isError,
|
|
1574
1519
|
chatFirstAppsQuery.isLoading,
|
|
1575
1520
|
chatFirstAppsQuery.refetch,
|
|
1576
|
-
|
|
1577
|
-
chatFirstConnectedAppsQuery.isError,
|
|
1578
|
-
chatFirstConnectedAppsQuery.isLoading,
|
|
1579
|
-
chatFirstConnectedAppsQuery.refetch,
|
|
1580
|
-
chatFirstAppItems,
|
|
1581
|
-
chatHomeWorkspaceApps,
|
|
1521
|
+
chatFirstWorkspaceApps,
|
|
1582
1522
|
openChatFirstApp,
|
|
1583
1523
|
],
|
|
1584
1524
|
);
|
|
@@ -1776,10 +1716,7 @@ export function Layout({
|
|
|
1776
1716
|
);
|
|
1777
1717
|
const resolveChatFirstOpenApp = useCallback(
|
|
1778
1718
|
(detail: ChatFirstOpenAppDetail) => {
|
|
1779
|
-
if (
|
|
1780
|
-
chatFirstAppsQuery.isLoading ||
|
|
1781
|
-
chatFirstConnectedAppsQuery.isLoading
|
|
1782
|
-
) {
|
|
1719
|
+
if (chatFirstAppsQuery.isLoading) {
|
|
1783
1720
|
pendingChatFirstOpenAppRef.current = detail;
|
|
1784
1721
|
return;
|
|
1785
1722
|
}
|
|
@@ -1823,7 +1760,6 @@ export function Layout({
|
|
|
1823
1760
|
chatFirstAppRegistrations,
|
|
1824
1761
|
chatFirstAppsQuery.isError,
|
|
1825
1762
|
chatFirstAppsQuery.isLoading,
|
|
1826
|
-
chatFirstConnectedAppsQuery.isLoading,
|
|
1827
1763
|
chatFirstSurfaceTabsStore,
|
|
1828
1764
|
openChatFirstPane,
|
|
1829
1765
|
navigate,
|
|
@@ -2032,19 +1968,12 @@ export function Layout({
|
|
|
2032
1968
|
|
|
2033
1969
|
useEffect(() => {
|
|
2034
1970
|
const pending = pendingChatFirstOpenAppRef.current;
|
|
2035
|
-
if (
|
|
2036
|
-
!pending ||
|
|
2037
|
-
chatFirstAppsQuery.isLoading ||
|
|
2038
|
-
chatFirstConnectedAppsQuery.isLoading
|
|
2039
|
-
)
|
|
2040
|
-
return;
|
|
1971
|
+
if (!pending || chatFirstAppsQuery.isLoading) return;
|
|
2041
1972
|
resolveChatFirstOpenApp(pending);
|
|
2042
1973
|
}, [
|
|
2043
1974
|
chatFirstAppsQuery.data,
|
|
2044
1975
|
chatFirstAppsQuery.isError,
|
|
2045
1976
|
chatFirstAppsQuery.isLoading,
|
|
2046
|
-
chatFirstConnectedAppsQuery.data,
|
|
2047
|
-
chatFirstConnectedAppsQuery.isLoading,
|
|
2048
1977
|
resolveChatFirstOpenApp,
|
|
2049
1978
|
]);
|
|
2050
1979
|
|
|
@@ -2302,6 +2231,51 @@ export function Layout({
|
|
|
2302
2231
|
],
|
|
2303
2232
|
);
|
|
2304
2233
|
|
|
2234
|
+
const chatFirstSurfaceTabsBar =
|
|
2235
|
+
activeChatFirstSurfaceTab?.kind === "app" ? null : (
|
|
2236
|
+
<ChatFirstSurfaceTabs
|
|
2237
|
+
tabs={chatFirstSurfaceTabs.tabs}
|
|
2238
|
+
activeTabId={chatFirstSurfaceTabs.activeTabId}
|
|
2239
|
+
onActivate={activateChatFirstSurfaceTab}
|
|
2240
|
+
onClose={closeChatFirstSurfaceTab}
|
|
2241
|
+
onCloseOthers={(tab) => {
|
|
2242
|
+
activateChatFirstSurfaceTab(tab);
|
|
2243
|
+
chatFirstSurfaceTabsStore.closeOthers(tab.id);
|
|
2244
|
+
}}
|
|
2245
|
+
onCloseToRight={(tab) => {
|
|
2246
|
+
const targetIndex = chatFirstSurfaceTabs.tabs.findIndex(
|
|
2247
|
+
(candidate) => candidate.id === tab.id,
|
|
2248
|
+
);
|
|
2249
|
+
const activeIndex = chatFirstSurfaceTabs.tabs.findIndex(
|
|
2250
|
+
(candidate) => candidate.id === chatFirstSurfaceTabs.activeTabId,
|
|
2251
|
+
);
|
|
2252
|
+
if (activeIndex > targetIndex) activateChatFirstSurfaceTab(tab);
|
|
2253
|
+
chatFirstSurfaceTabsStore.closeToRight(tab.id);
|
|
2254
|
+
}}
|
|
2255
|
+
onCloseAll={closeAllChatFirstSurfaceTabs}
|
|
2256
|
+
onOpenSurface={openChatFirstSurface}
|
|
2257
|
+
apps={chatFirstAppItems}
|
|
2258
|
+
onOpenApp={(app) => openChatFirstPane({ appId: app.id }, "side")}
|
|
2259
|
+
renderAppIcon={(app) => (
|
|
2260
|
+
<AppIcon
|
|
2261
|
+
id={app.id}
|
|
2262
|
+
name={app.name}
|
|
2263
|
+
size="sm"
|
|
2264
|
+
className="size-7 rounded-lg"
|
|
2265
|
+
/>
|
|
2266
|
+
)}
|
|
2267
|
+
copy={chatFirstCopy}
|
|
2268
|
+
/>
|
|
2269
|
+
);
|
|
2270
|
+
const chatFirstSurfaceContent =
|
|
2271
|
+
chatFirstSurfaceTabs.tabs.length > 0 ? (
|
|
2272
|
+
<ChatFirstSurfaceContent
|
|
2273
|
+
tabs={chatFirstSurfaceTabs.tabs}
|
|
2274
|
+
activeTabId={chatFirstSurfaceTabs.activeTabId}
|
|
2275
|
+
renderTab={renderChatFirstSurfaceTab}
|
|
2276
|
+
/>
|
|
2277
|
+
) : null;
|
|
2278
|
+
|
|
2305
2279
|
if (CHROMELESS_PATHS.some((path) => localPathname === path)) {
|
|
2306
2280
|
return <>{children}</>;
|
|
2307
2281
|
}
|
|
@@ -2320,10 +2294,32 @@ export function Layout({
|
|
|
2320
2294
|
<div className="relative flex min-w-0 flex-1 flex-col overflow-hidden">
|
|
2321
2295
|
<Header showAgentToggle={false} />
|
|
2322
2296
|
<InvitationBanner />
|
|
2323
|
-
<main className="flex-1 overflow-
|
|
2324
|
-
<div className="
|
|
2325
|
-
|
|
2297
|
+
<main className="relative flex min-h-0 flex-1 overflow-hidden">
|
|
2298
|
+
<div className="min-w-0 flex-1 overflow-y-auto">
|
|
2299
|
+
<div className="mx-auto max-w-7xl space-y-10 px-4 py-6 sm:px-6">
|
|
2300
|
+
{children}
|
|
2301
|
+
</div>
|
|
2326
2302
|
</div>
|
|
2303
|
+
{isChatRoute &&
|
|
2304
|
+
chatFirstMode &&
|
|
2305
|
+
chatFirstHasActiveChat &&
|
|
2306
|
+
chatFirstSurfacePanel.open ? (
|
|
2307
|
+
<ChatFirstSurfacePanel
|
|
2308
|
+
width={chatFirstSurfaceResize.width}
|
|
2309
|
+
onResizePointerDown={chatFirstSurfaceResize.onPointerDown}
|
|
2310
|
+
copy={chatFirstCopy}
|
|
2311
|
+
>
|
|
2312
|
+
{chatFirstSurfaceTabsBar}
|
|
2313
|
+
{chatFirstSurfaceContent}
|
|
2314
|
+
</ChatFirstSurfacePanel>
|
|
2315
|
+
) : null}
|
|
2316
|
+
{isChatRoute && chatFirstMode && chatFirstHasActiveChat ? (
|
|
2317
|
+
<ChatFirstSurfacePanelToggle
|
|
2318
|
+
open={chatFirstSurfacePanel.open}
|
|
2319
|
+
onToggle={chatFirstSurfacePanel.toggle}
|
|
2320
|
+
className={CHAT_FIRST_SURFACE_PANEL_TOGGLE_CLASS_NAME}
|
|
2321
|
+
/>
|
|
2322
|
+
) : null}
|
|
2327
2323
|
</main>
|
|
2328
2324
|
</div>
|
|
2329
2325
|
</div>
|
|
@@ -2349,7 +2345,9 @@ export function Layout({
|
|
|
2349
2345
|
}
|
|
2350
2346
|
|
|
2351
2347
|
const showAgentControls =
|
|
2352
|
-
!isChatRoute &&
|
|
2348
|
+
!isChatRoute &&
|
|
2349
|
+
!isRedesignedSettingsRoute &&
|
|
2350
|
+
!pageOwnsToolbar(localPathname);
|
|
2353
2351
|
function openAskAgentFullscreen() {
|
|
2354
2352
|
focusAgentChat();
|
|
2355
2353
|
navigateWithAgentChatViewTransition(
|
|
@@ -2382,13 +2380,6 @@ export function Layout({
|
|
|
2382
2380
|
const appContent = (
|
|
2383
2381
|
<div className="relative flex h-full min-h-0 min-w-0 flex-1 flex-col overflow-hidden">
|
|
2384
2382
|
<InvitationBanner />
|
|
2385
|
-
{isChatRoute && chatFirstMode && chatFirstHasActiveChat ? (
|
|
2386
|
-
<ChatFirstSurfacePanelToggle
|
|
2387
|
-
open={chatFirstSurfacePanel.open}
|
|
2388
|
-
onToggle={chatFirstSurfacePanel.toggle}
|
|
2389
|
-
className={CHAT_FIRST_SURFACE_PANEL_TOGGLE_CLASS_NAME}
|
|
2390
|
-
/>
|
|
2391
|
-
) : null}
|
|
2392
2383
|
{isChatRoute && chatFirstMode && chatFirstNotice ? (
|
|
2393
2384
|
<div
|
|
2394
2385
|
className="dispatch-chat-first-notice"
|
|
@@ -2450,68 +2441,25 @@ export function Layout({
|
|
|
2450
2441
|
</main>
|
|
2451
2442
|
</div>
|
|
2452
2443
|
);
|
|
2453
|
-
const
|
|
2454
|
-
|
|
2455
|
-
|
|
2456
|
-
|
|
2457
|
-
|
|
2458
|
-
onActivate={activateChatFirstSurfaceTab}
|
|
2459
|
-
onClose={closeChatFirstSurfaceTab}
|
|
2460
|
-
onCloseOthers={(tab) => {
|
|
2461
|
-
activateChatFirstSurfaceTab(tab);
|
|
2462
|
-
chatFirstSurfaceTabsStore.closeOthers(tab.id);
|
|
2463
|
-
}}
|
|
2464
|
-
onCloseToRight={(tab) => {
|
|
2465
|
-
const targetIndex = chatFirstSurfaceTabs.tabs.findIndex(
|
|
2466
|
-
(candidate) => candidate.id === tab.id,
|
|
2467
|
-
);
|
|
2468
|
-
const activeIndex = chatFirstSurfaceTabs.tabs.findIndex(
|
|
2469
|
-
(candidate) => candidate.id === chatFirstSurfaceTabs.activeTabId,
|
|
2470
|
-
);
|
|
2471
|
-
if (activeIndex > targetIndex) activateChatFirstSurfaceTab(tab);
|
|
2472
|
-
chatFirstSurfaceTabsStore.closeToRight(tab.id);
|
|
2473
|
-
}}
|
|
2474
|
-
onCloseAll={closeAllChatFirstSurfaceTabs}
|
|
2475
|
-
onOpenSurface={openChatFirstSurface}
|
|
2476
|
-
apps={chatFirstAppItems}
|
|
2477
|
-
onOpenApp={(app) => openChatFirstPane({ appId: app.id }, "side")}
|
|
2478
|
-
renderAppIcon={(app) => (
|
|
2479
|
-
<AppIcon
|
|
2480
|
-
id={app.id}
|
|
2481
|
-
name={app.name}
|
|
2482
|
-
size="sm"
|
|
2483
|
-
className="size-7 rounded-lg"
|
|
2484
|
-
/>
|
|
2485
|
-
)}
|
|
2486
|
-
copy={chatFirstCopy}
|
|
2487
|
-
/>
|
|
2488
|
-
);
|
|
2489
|
-
const chatFirstSurfaceContent =
|
|
2490
|
-
chatFirstSurfaceTabs.tabs.length > 0 ? (
|
|
2491
|
-
<ChatFirstSurfaceContent
|
|
2492
|
-
tabs={chatFirstSurfaceTabs.tabs}
|
|
2493
|
-
activeTabId={chatFirstSurfaceTabs.activeTabId}
|
|
2494
|
-
renderTab={renderChatFirstSurfaceTab}
|
|
2495
|
-
/>
|
|
2496
|
-
) : null;
|
|
2497
|
-
const workspaceAppChatName =
|
|
2498
|
-
(workspaceAppId
|
|
2499
|
-
? chatFirstAppRegistrations.find(
|
|
2500
|
-
(app) => app.id.toLowerCase() === workspaceAppId.toLowerCase(),
|
|
2501
|
-
)?.name
|
|
2502
|
-
: null) ??
|
|
2503
|
-
workspaceAppId ??
|
|
2504
|
-
"Workspace app";
|
|
2444
|
+
const workspaceAppChatRegistration = workspaceAppId
|
|
2445
|
+
? chatFirstAppRegistrations.find(
|
|
2446
|
+
(app) => app.id.toLowerCase() === workspaceAppId.toLowerCase(),
|
|
2447
|
+
)
|
|
2448
|
+
: undefined;
|
|
2505
2449
|
const workspaceAppContent =
|
|
2506
2450
|
workspaceAppRouteActive && workspaceAppId ? (
|
|
2507
|
-
|
|
2508
|
-
|
|
2509
|
-
|
|
2510
|
-
|
|
2511
|
-
|
|
2512
|
-
|
|
2451
|
+
workspaceAppChatRegistration ? (
|
|
2452
|
+
<WorkspaceAppChatRail
|
|
2453
|
+
appId={workspaceAppId}
|
|
2454
|
+
appName={workspaceAppChatRegistration.name ?? workspaceAppId}
|
|
2455
|
+
agentPageHref={agentPageHref}
|
|
2456
|
+
onFullscreenRequest={openAskAgentFullscreen}
|
|
2457
|
+
>
|
|
2458
|
+
<WorkspaceAppKeepAlive activeAppId={workspaceAppId} />
|
|
2459
|
+
</WorkspaceAppChatRail>
|
|
2460
|
+
) : (
|
|
2513
2461
|
<WorkspaceAppKeepAlive activeAppId={workspaceAppId} />
|
|
2514
|
-
|
|
2462
|
+
)
|
|
2515
2463
|
) : (
|
|
2516
2464
|
<WorkspaceAppKeepAlive
|
|
2517
2465
|
activeAppId={workspaceAppRouteActive ? workspaceAppId : null}
|
|
@@ -2572,7 +2520,7 @@ export function Layout({
|
|
|
2572
2520
|
<DispatchWorkspaceAppLauncherContext.Provider value={chatHomeAppLauncher}>
|
|
2573
2521
|
<HeaderActionsProvider>
|
|
2574
2522
|
<div className="agent-layout-shell flex h-screen w-full overflow-hidden bg-background">
|
|
2575
|
-
{
|
|
2523
|
+
{isRedesignedSettingsRoute ? null : (
|
|
2576
2524
|
<aside
|
|
2577
2525
|
data-collapsed={sidebarCollapsed ? "true" : "false"}
|
|
2578
2526
|
className={cn(
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
// @vitest-environment happy-dom
|
|
2
|
+
import React, { act } from "react";
|
|
3
|
+
import { createRoot, type Root } from "react-dom/client";
|
|
4
|
+
import { MemoryRouter } from "react-router";
|
|
5
|
+
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
|
6
|
+
|
|
7
|
+
const clientState = vi.hoisted(() => ({
|
|
8
|
+
actions: [] as string[],
|
|
9
|
+
}));
|
|
10
|
+
|
|
11
|
+
vi.mock("@agent-native/core/client/hooks", () => ({
|
|
12
|
+
useActionQuery: (action: string) => {
|
|
13
|
+
clientState.actions.push(action);
|
|
14
|
+
return {
|
|
15
|
+
data:
|
|
16
|
+
action === "list-workspace-apps"
|
|
17
|
+
? [
|
|
18
|
+
{
|
|
19
|
+
id: "reports",
|
|
20
|
+
name: "Reports",
|
|
21
|
+
path: "/reports",
|
|
22
|
+
url: "/reports",
|
|
23
|
+
status: "ready",
|
|
24
|
+
},
|
|
25
|
+
]
|
|
26
|
+
: [
|
|
27
|
+
{
|
|
28
|
+
id: "internal-app",
|
|
29
|
+
name: "Internal app",
|
|
30
|
+
url: "https://internal.example.test",
|
|
31
|
+
homeUrl: "https://internal.example.test",
|
|
32
|
+
source: "builtin",
|
|
33
|
+
},
|
|
34
|
+
],
|
|
35
|
+
isError: false,
|
|
36
|
+
};
|
|
37
|
+
},
|
|
38
|
+
}));
|
|
39
|
+
|
|
40
|
+
vi.mock("@agent-native/core/client/i18n", () => ({
|
|
41
|
+
useT: () => (_key: string, values?: { defaultValue?: string }) =>
|
|
42
|
+
values?.defaultValue ?? "Workspace apps",
|
|
43
|
+
}));
|
|
44
|
+
|
|
45
|
+
import { WorkspaceAppsRail } from "./workspace-apps-rail";
|
|
46
|
+
|
|
47
|
+
describe("WorkspaceAppsRail", () => {
|
|
48
|
+
let container: HTMLDivElement;
|
|
49
|
+
let root: Root;
|
|
50
|
+
|
|
51
|
+
beforeEach(() => {
|
|
52
|
+
vi.stubGlobal("IS_REACT_ACT_ENVIRONMENT", true);
|
|
53
|
+
clientState.actions = [];
|
|
54
|
+
container = document.createElement("div");
|
|
55
|
+
document.body.appendChild(container);
|
|
56
|
+
root = createRoot(container);
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
afterEach(() => {
|
|
60
|
+
act(() => root.unmount());
|
|
61
|
+
container.remove();
|
|
62
|
+
vi.unstubAllGlobals();
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
it("lists mounted workspace apps without connected agents", async () => {
|
|
66
|
+
await act(async () => {
|
|
67
|
+
root.render(
|
|
68
|
+
<MemoryRouter initialEntries={["/overview"]}>
|
|
69
|
+
<WorkspaceAppsRail />
|
|
70
|
+
</MemoryRouter>,
|
|
71
|
+
);
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
expect(container.textContent).toContain("Reports");
|
|
75
|
+
expect(container.textContent).not.toContain("Internal app");
|
|
76
|
+
expect(container.querySelector('a[href="/apps/reports"]')).not.toBeNull();
|
|
77
|
+
expect(clientState.actions).toEqual(["list-workspace-apps"]);
|
|
78
|
+
});
|
|
79
|
+
});
|
|
@@ -3,10 +3,6 @@ import { useT } from "@agent-native/core/client/i18n";
|
|
|
3
3
|
import { IconApps } from "@tabler/icons-react";
|
|
4
4
|
import { Link, useLocation } from "react-router";
|
|
5
5
|
|
|
6
|
-
import {
|
|
7
|
-
filterOtherApps,
|
|
8
|
-
type ConnectedAppSummary,
|
|
9
|
-
} from "../../lib/other-apps";
|
|
10
6
|
import { cn } from "../../lib/utils";
|
|
11
7
|
import {
|
|
12
8
|
isWorkspaceAppVisibleInDefaultLaunchers,
|
|
@@ -26,7 +22,7 @@ function appLabel(app: WorkspaceAppSummary): string {
|
|
|
26
22
|
return app.name.trim() || app.id;
|
|
27
23
|
}
|
|
28
24
|
|
|
29
|
-
type RailApp = WorkspaceAppSummary
|
|
25
|
+
type RailApp = WorkspaceAppSummary;
|
|
30
26
|
|
|
31
27
|
export function WorkspaceAppsRail({
|
|
32
28
|
collapsed = false,
|
|
@@ -43,33 +39,17 @@ export function WorkspaceAppsRail({
|
|
|
43
39
|
includeAgentCards: false,
|
|
44
40
|
},
|
|
45
41
|
);
|
|
46
|
-
const connectedAppsQuery = useActionQuery<ConnectedAppSummary[]>(
|
|
47
|
-
"list-connected-agents",
|
|
48
|
-
{},
|
|
49
|
-
);
|
|
50
42
|
if (appsQuery.isError || !appsQuery.data) return null;
|
|
51
43
|
|
|
52
|
-
const
|
|
53
|
-
|
|
54
|
-
...workspaceApps.filter(
|
|
44
|
+
const apps: RailApp[] = appsQuery.data
|
|
45
|
+
.filter(
|
|
55
46
|
(app) =>
|
|
56
47
|
isWorkspaceAppVisibleInDefaultLaunchers(app) &&
|
|
57
48
|
!app.archived &&
|
|
58
49
|
app.status !== "pending" &&
|
|
59
50
|
!!workspaceAppHref(app),
|
|
60
|
-
)
|
|
61
|
-
|
|
62
|
-
(app) => ({
|
|
63
|
-
id: app.id,
|
|
64
|
-
name: app.name,
|
|
65
|
-
description: app.description,
|
|
66
|
-
path: "",
|
|
67
|
-
url: app.homeUrl ?? app.url,
|
|
68
|
-
status: "ready" as const,
|
|
69
|
-
external: true,
|
|
70
|
-
}),
|
|
71
|
-
),
|
|
72
|
-
].sort((a, b) => appLabel(a).localeCompare(appLabel(b)));
|
|
51
|
+
)
|
|
52
|
+
.sort((a, b) => appLabel(a).localeCompare(appLabel(b)));
|
|
73
53
|
|
|
74
54
|
if (apps.length === 0) return null;
|
|
75
55
|
|
|
@@ -102,11 +82,7 @@ export function WorkspaceAppsRail({
|
|
|
102
82
|
{!collapsed ? <span className="truncate">{label}</span> : null}
|
|
103
83
|
</>
|
|
104
84
|
);
|
|
105
|
-
const link =
|
|
106
|
-
<a href={href} {...linkProps}>
|
|
107
|
-
{linkContent}
|
|
108
|
-
</a>
|
|
109
|
-
) : (
|
|
85
|
+
const link = (
|
|
110
86
|
<Link to={workspaceAppRoute(app.id)} {...linkProps}>
|
|
111
87
|
{linkContent}
|
|
112
88
|
</Link>
|