@agent-native/dispatch 0.20.3 → 0.21.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/actions/provider-api-register.d.ts +6 -6
- package/dist/actions/start-workspace-app-creation.js +1 -1
- package/dist/actions/start-workspace-app-creation.js.map +1 -1
- package/dist/components/automation-run-history-dialog.d.ts.map +1 -1
- package/dist/components/automation-run-history-dialog.js +1 -0
- package/dist/components/automation-run-history-dialog.js.map +1 -1
- package/dist/components/create-app-popover.d.ts.map +1 -1
- package/dist/components/create-app-popover.js +5 -71
- package/dist/components/create-app-popover.js.map +1 -1
- package/dist/components/layout/Layout.d.ts +23 -1
- package/dist/components/layout/Layout.d.ts.map +1 -1
- package/dist/components/layout/Layout.js +702 -15
- package/dist/components/layout/Layout.js.map +1 -1
- package/dist/lib/automation-display.d.ts +6 -0
- package/dist/lib/automation-display.d.ts.map +1 -1
- package/dist/lib/automation-display.js +8 -0
- package/dist/lib/automation-display.js.map +1 -1
- package/dist/lib/automations.d.ts +1 -0
- package/dist/lib/automations.d.ts.map +1 -1
- package/dist/lib/automations.js.map +1 -1
- package/dist/lib/workspace-apps.d.ts +6 -0
- package/dist/lib/workspace-apps.d.ts.map +1 -1
- package/dist/lib/workspace-apps.js +21 -0
- package/dist/lib/workspace-apps.js.map +1 -1
- package/dist/routes/pages/automations.d.ts.map +1 -1
- package/dist/routes/pages/automations.js +16 -6
- package/dist/routes/pages/automations.js.map +1 -1
- package/dist/routes/pages/settings.d.ts.map +1 -1
- package/dist/routes/pages/settings.js +21 -1
- package/dist/routes/pages/settings.js.map +1 -1
- package/dist/server/index.d.ts +1 -1
- package/dist/server/index.d.ts.map +1 -1
- package/dist/server/index.js +1 -1
- package/dist/server/index.js.map +1 -1
- package/dist/server/lib/app-creation-store.d.ts.map +1 -1
- package/dist/server/lib/app-creation-store.js +13 -0
- package/dist/server/lib/app-creation-store.js.map +1 -1
- package/dist/server/plugins/agent-chat.js +1 -0
- package/dist/server/plugins/agent-chat.js.map +1 -1
- package/dist/server/plugins/db.d.ts +1 -0
- package/dist/server/plugins/db.d.ts.map +1 -1
- package/dist/server/plugins/db.js +1 -1
- package/dist/server/plugins/db.js.map +1 -1
- package/dist/server/plugins/integrations.js +1 -1
- package/dist/server/plugins/integrations.js.map +1 -1
- package/package.json +3 -3
- package/src/actions/start-workspace-app-creation.ts +1 -1
- package/src/components/automation-run-history-dialog.tsx +1 -0
- package/src/components/create-app-popover.spec.tsx +22 -0
- package/src/components/create-app-popover.tsx +30 -94
- package/src/components/layout/Layout.spec.tsx +16 -1
- package/src/components/layout/Layout.tsx +1356 -34
- package/src/lib/automation-display.spec.ts +7 -0
- package/src/lib/automation-display.ts +11 -0
- package/src/lib/automations.ts +1 -0
- package/src/lib/workspace-apps.ts +24 -0
- package/src/routes/pages/automations.tsx +45 -6
- package/src/routes/pages/settings.tsx +72 -0
- package/src/server/index.ts +4 -1
- package/src/server/lib/app-creation-store.spec.ts +13 -0
- package/src/server/lib/app-creation-store.ts +13 -0
- package/src/server/lib/mcp-gateway.spec.ts +18 -0
- package/src/server/plugins/agent-chat.ts +1 -0
- package/src/server/plugins/db.ts +1 -1
- package/src/server/plugins/integrations.ts +1 -1
- package/src/styles/dispatch.css +29 -0
|
@@ -1,16 +1,24 @@
|
|
|
1
1
|
import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { AgentSidebar, focusAgentChat, navigateWithAgentChatViewTransition, useAgentChatHomeHandoff, useAgentChatHomeHandoffLinks, useChatThreads, } from "@agent-native/core/client/agent-chat";
|
|
2
|
+
import { CHAT_FIRST_MODE_CHANGED_EVENT, AgentChatSurface, chatFirstSurfaceTabId, AgentSidebar, ChatFirstSurfacePanelToggle, closeChatFirstSessionWatch, emitChatFirstSessionWatch, getChatFirstSurfaceTabsStore, focusAgentChat, navigateWithAgentChatViewTransition, readChatFirstAppLayout, readChatFirstMode, resolveChatFirstBrowserTarget, resolveChatFirstAppTarget, subscribeChatFirstOpenBrowser, subscribeChatFirstOpenApp, useChatFirstSessionWatch, useChatFirstSurfacePanel, useChatFirstSurfaceResize, useChatFirstSurfaceTabs, useAgentChatHomeHandoff, useAgentChatHomeHandoffLinks, useChatThreads, } from "@agent-native/core/client/agent-chat";
|
|
3
3
|
import { appBasePath, appPath } from "@agent-native/core/client/api-path";
|
|
4
|
+
import { readClientAppState, writeClientAppState, } from "@agent-native/core/client/application-state";
|
|
5
|
+
import { ChatFirstAgentsPane, ChatFirstAppPane, ChatFirstAppsRail, ChatFirstBrowserPane, ChatFirstChatHistory, ChatFirstPrimaryNavigation, ChatFirstSessionWatchPane, ChatFirstSurfacePanel, ChatFirstSurfaceContent, ChatFirstSurfaceTabs, defaultChatFirstCopy, } from "@agent-native/core/client/chat-first";
|
|
6
|
+
import { writeClipboardText } from "@agent-native/core/client/clipboard";
|
|
7
|
+
import { useActionMutation, useActionQuery, } from "@agent-native/core/client/hooks";
|
|
4
8
|
import { useT } from "@agent-native/core/client/i18n";
|
|
5
9
|
import { openCommandMenu } from "@agent-native/core/client/navigation";
|
|
6
10
|
import { InvitationBanner, OrgSwitcher } from "@agent-native/core/client/org";
|
|
7
11
|
import { FeedbackButton } from "@agent-native/core/client/ui";
|
|
8
12
|
import { SidebarFooterActions } from "@agent-native/toolkit/app-shell";
|
|
9
13
|
import { ChatHistoryRail, } from "@agent-native/toolkit/chat-history";
|
|
10
|
-
import { IconApps, IconBrandSlack, IconBrandTelegram, IconMessageQuestion, IconBroadcast, IconLayoutSidebarLeftCollapse, IconLayoutSidebarLeftExpand, IconSettings, IconShield, IconSearch, IconWorld, IconDeviceDesktop, } from "@tabler/icons-react";
|
|
11
|
-
import { createContext, useEffect, useMemo, useRef, useState, useContext, } from "react";
|
|
14
|
+
import { IconApps, IconBrandSlack, IconBrandTelegram, IconCopy, IconEye, IconMessageQuestion, IconBroadcast, IconLayoutSidebarLeftCollapse, IconLayoutSidebarLeftExpand, IconSettings, IconShield, IconSearch, IconWorld, IconDeviceDesktop, IconPlus, } from "@tabler/icons-react";
|
|
15
|
+
import { createContext, useEffect, useMemo, useRef, useState, useContext, useCallback, } from "react";
|
|
12
16
|
import { Link, useLocation, useNavigate } from "react-router";
|
|
17
|
+
import { toast } from "sonner";
|
|
13
18
|
import { cn } from "../../lib/utils.js";
|
|
19
|
+
import { mergeChatFirstWorkspaceApps, } from "../../lib/workspace-apps.js";
|
|
20
|
+
import { AppIcon } from "../app-icon.js";
|
|
21
|
+
import { CreateAppPopover } from "../create-app-popover.js";
|
|
14
22
|
import { Sheet, SheetContent, SheetDescription, SheetTitle } from "../ui/sheet.js";
|
|
15
23
|
import { Skeleton } from "../ui/skeleton.js";
|
|
16
24
|
import { Tooltip, TooltipContent, TooltipTrigger } from "../ui/tooltip.js";
|
|
@@ -59,6 +67,10 @@ const DISPATCH_SIDEBAR_LABEL = "Dispatch";
|
|
|
59
67
|
const CHROMELESS_PATHS = ["/approval", "/browser-chat", "/browser-connect"];
|
|
60
68
|
const SIDEBAR_COLLAPSE_KEY = "dispatch.sidebar.collapsed";
|
|
61
69
|
const CHAT_HISTORY_SOURCE_KEY = "dispatch.chat-history.source";
|
|
70
|
+
const CHAT_FIRST_PANE_STATE_KEY = "chat-first-pane";
|
|
71
|
+
export function buildChatFirstEmbedSessionInput(appId, path) {
|
|
72
|
+
return { app: appId, path, chrome: "minimal" };
|
|
73
|
+
}
|
|
62
74
|
const DispatchExtensionsContext = createContext(undefined);
|
|
63
75
|
export function useDispatchExtensions() {
|
|
64
76
|
return useContext(DispatchExtensionsContext);
|
|
@@ -120,8 +132,147 @@ function dispatchNavLinkTarget(path) {
|
|
|
120
132
|
const routerHasBasename = pathname === basePath || pathname.startsWith(`${basePath}/`);
|
|
121
133
|
return routerHasBasename ? path : appPath(path);
|
|
122
134
|
}
|
|
135
|
+
function chatFirstResolutionMessage(reason) {
|
|
136
|
+
switch (reason) {
|
|
137
|
+
case "empty-detail":
|
|
138
|
+
return "The agent did not provide an app target to open.";
|
|
139
|
+
case "invalid-url":
|
|
140
|
+
return "The requested app route was not registered for this workspace app.";
|
|
141
|
+
case "unknown-app":
|
|
142
|
+
return "That app is not available in this workspace.";
|
|
143
|
+
}
|
|
144
|
+
return "The requested app could not be opened.";
|
|
145
|
+
}
|
|
146
|
+
function chatFirstBrowserResolutionMessage(reason) {
|
|
147
|
+
return reason === "empty-detail"
|
|
148
|
+
? "The agent did not provide a browser URL to open."
|
|
149
|
+
: "The requested browser URL is not a safe HTTP(S) address.";
|
|
150
|
+
}
|
|
151
|
+
const DISPATCH_CHAT_FIRST_COPY_KEYS = {
|
|
152
|
+
workspaceApps: "chatFirstWorkspaceApps",
|
|
153
|
+
createWorkspaceApp: "chatFirstCreateWorkspaceApp",
|
|
154
|
+
openApp: "chatFirstOpenApp",
|
|
155
|
+
appsLoadError: "chatFirstAppsLoadError",
|
|
156
|
+
noWorkspaceApps: "chatFirstNoWorkspaceApps",
|
|
157
|
+
createApp: "chatFirstCreateApp",
|
|
158
|
+
retry: "chatFirstRetry",
|
|
159
|
+
dismiss: "chatFirstDismiss",
|
|
160
|
+
unpinApp: "chatFirstUnpinApp",
|
|
161
|
+
pinApp: "chatFirstPinApp",
|
|
162
|
+
removePinned: "chatFirstRemovePinned",
|
|
163
|
+
pinTop: "chatFirstPinTop",
|
|
164
|
+
openSideSurfaces: "chatFirstOpenSideSurfaces",
|
|
165
|
+
closeTab: "chatFirstCloseTab",
|
|
166
|
+
close: "chatFirstClose",
|
|
167
|
+
closeOthers: "chatFirstCloseOthers",
|
|
168
|
+
closeToRight: "chatFirstCloseToRight",
|
|
169
|
+
closeAll: "chatFirstCloseAll",
|
|
170
|
+
unavailable: "chatFirstUnavailable",
|
|
171
|
+
openActivity: "chatFirstOpenActivity",
|
|
172
|
+
deferred: "chatFirstDeferred",
|
|
173
|
+
browserBack: "chatFirstBrowserBack",
|
|
174
|
+
browserForward: "chatFirstBrowserForward",
|
|
175
|
+
browserReload: "chatFirstBrowserReload",
|
|
176
|
+
browserAddress: "chatFirstBrowserAddress",
|
|
177
|
+
browserOpenExternal: "chatFirstBrowserOpenExternal",
|
|
178
|
+
browserClose: "chatFirstBrowserClose",
|
|
179
|
+
browserPage: "chatFirstBrowserPage",
|
|
180
|
+
browserInvalidUrl: "chatFirstBrowserInvalidUrl",
|
|
181
|
+
browserPreviewStarting: "chatFirstBrowserPreviewStarting",
|
|
182
|
+
browserPreviewError: "chatFirstBrowserPreviewError",
|
|
183
|
+
appUnavailable: "chatFirstAppUnavailable",
|
|
184
|
+
appLoading: "chatFirstLoadingApp",
|
|
185
|
+
agentActivityEyebrow: "chatFirstAgentActivityEyebrow",
|
|
186
|
+
agentActivityTitle: "chatFirstAgentActivityTitle",
|
|
187
|
+
agentActivityDescription: "chatFirstAgentActivityDescription",
|
|
188
|
+
refreshAgentActivity: "chatFirstRefreshAgentActivity",
|
|
189
|
+
noAgentSessions: "chatFirstNoAgentSessions",
|
|
190
|
+
startAgentSession: "chatFirstStartAgentSession",
|
|
191
|
+
watchSession: "chatFirstWatchSession",
|
|
192
|
+
copySessionId: "chatFirstCopySessionId",
|
|
193
|
+
copySessionIdFor: "chatFirstCopySessionIdFor",
|
|
194
|
+
sessionIdCopied: "chatFirstSessionIdCopied",
|
|
195
|
+
sessionIdShort: "chatFirstSessionIdShort",
|
|
196
|
+
copied: "chatFirstCopied",
|
|
197
|
+
agentActivityStatusQueued: "chatFirstAgentActivityStatusQueued",
|
|
198
|
+
agentActivityStatusRunning: "chatFirstAgentActivityStatusRunning",
|
|
199
|
+
agentActivityStatusPaused: "chatFirstAgentActivityStatusPaused",
|
|
200
|
+
agentActivityStatusNeedsApproval: "chatFirstAgentActivityStatusNeedsApproval",
|
|
201
|
+
agentActivityStatusCompleted: "chatFirstAgentActivityStatusCompleted",
|
|
202
|
+
agentActivityStatusErrored: "chatFirstAgentActivityStatusErrored",
|
|
203
|
+
agentActivityStatusRecent: "chatFirstAgentActivityStatusRecent",
|
|
204
|
+
agentActivityStatusUnknown: "chatFirstAgentActivityStatusUnknown",
|
|
205
|
+
watchingSession: "chatFirstWatchingSession",
|
|
206
|
+
session: "chatFirstSession",
|
|
207
|
+
stopWatchingSession: "chatFirstStopWatchingSession",
|
|
208
|
+
stopWatching: "chatFirstStopWatching",
|
|
209
|
+
watchedSession: "chatFirstWatchedSession",
|
|
210
|
+
agentsTitle: "chatFirstAgentsTitle",
|
|
211
|
+
};
|
|
212
|
+
const DISPATCH_CHAT_FIRST_SURFACE_COPY_KEYS = {
|
|
213
|
+
browser: {
|
|
214
|
+
label: "chatFirstSurfaceBrowserLabel",
|
|
215
|
+
reason: "chatFirstSurfaceBrowserReason",
|
|
216
|
+
},
|
|
217
|
+
terminal: {
|
|
218
|
+
label: "chatFirstSurfaceTerminalLabel",
|
|
219
|
+
reason: "chatFirstSurfaceTerminalReason",
|
|
220
|
+
},
|
|
221
|
+
files: {
|
|
222
|
+
label: "chatFirstSurfaceFilesLabel",
|
|
223
|
+
reason: "chatFirstSurfaceFilesReason",
|
|
224
|
+
},
|
|
225
|
+
diff: {
|
|
226
|
+
label: "chatFirstSurfaceDiffLabel",
|
|
227
|
+
reason: "chatFirstSurfaceDiffReason",
|
|
228
|
+
},
|
|
229
|
+
"side-chat": {
|
|
230
|
+
label: "chatFirstSurfaceSideChatLabel",
|
|
231
|
+
reason: "chatFirstSurfaceSideChatReason",
|
|
232
|
+
},
|
|
233
|
+
agents: {
|
|
234
|
+
label: "chatFirstSurfaceAgentsLabel",
|
|
235
|
+
reason: "chatFirstSurfaceAgentsReason",
|
|
236
|
+
},
|
|
237
|
+
};
|
|
238
|
+
function createDispatchChatFirstCopy(t) {
|
|
239
|
+
return (key, values) => {
|
|
240
|
+
if (key.startsWith("surface.")) {
|
|
241
|
+
const [, kind, field] = key.split(".");
|
|
242
|
+
const surface = DISPATCH_CHAT_FIRST_SURFACE_COPY_KEYS[kind];
|
|
243
|
+
const translationKey = surface && (field === "label" || field === "reason")
|
|
244
|
+
? surface[field]
|
|
245
|
+
: undefined;
|
|
246
|
+
if (translationKey) {
|
|
247
|
+
return t(`dispatch.pages.${translationKey}`, {
|
|
248
|
+
...(values ?? {}),
|
|
249
|
+
defaultValue: defaultChatFirstCopy(key, values),
|
|
250
|
+
});
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
const translationKey = DISPATCH_CHAT_FIRST_COPY_KEYS[key];
|
|
254
|
+
if (!translationKey)
|
|
255
|
+
return defaultChatFirstCopy(key, values);
|
|
256
|
+
return t(`dispatch.pages.${translationKey}`, {
|
|
257
|
+
...(values ?? {}),
|
|
258
|
+
defaultValue: defaultChatFirstCopy(key, values),
|
|
259
|
+
});
|
|
260
|
+
};
|
|
261
|
+
}
|
|
123
262
|
function chatThreadPath(threadId) {
|
|
124
|
-
return `/chat/${encodeURIComponent(threadId)}
|
|
263
|
+
return threadId ? `/chat/${encodeURIComponent(threadId)}` : "/chat";
|
|
264
|
+
}
|
|
265
|
+
function persistedChatFirstPane(value) {
|
|
266
|
+
if (!value || typeof value !== "object")
|
|
267
|
+
return null;
|
|
268
|
+
const record = value;
|
|
269
|
+
if (typeof record.appId !== "string" || !record.appId.trim())
|
|
270
|
+
return null;
|
|
271
|
+
return {
|
|
272
|
+
appId: record.appId,
|
|
273
|
+
...(typeof record.path === "string" ? { path: record.path } : {}),
|
|
274
|
+
...(typeof record.view === "string" ? { view: record.view } : {}),
|
|
275
|
+
};
|
|
125
276
|
}
|
|
126
277
|
function threadIdFromPath(pathname) {
|
|
127
278
|
const match = pathname.match(/^\/chat\/([^/]+)/);
|
|
@@ -185,7 +336,7 @@ function threadUpdatedAt(thread) {
|
|
|
185
336
|
? thread.createdAt
|
|
186
337
|
: 0;
|
|
187
338
|
}
|
|
188
|
-
function DispatchChatsSection({ onNavigate }) {
|
|
339
|
+
function DispatchChatsSection({ onNavigate, showNewChat = false, prelude, chatFirstMode = false, chatFirstEmbedded = false, }) {
|
|
189
340
|
const t = useT();
|
|
190
341
|
const navigate = useNavigate();
|
|
191
342
|
const location = useLocation();
|
|
@@ -266,7 +417,7 @@ function DispatchChatsSection({ onNavigate }) {
|
|
|
266
417
|
if (threadId)
|
|
267
418
|
openThread(threadId, { isNew: true });
|
|
268
419
|
}
|
|
269
|
-
return (_jsxs("div", { className: "ms-4 min-w-0 space-y-0.5", children: [_jsx("div", { className: "flex justify-end px-2 pt-0.5", children: _jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsx("button", { type: "button", "data-dispatch-chat-source-toggle": true, "aria-pressed": includeExternal, "aria-label": includeExternal
|
|
420
|
+
return (_jsxs("div", { className: cn("ms-4 min-w-0 space-y-0.5", showNewChat && "dispatch-chat-first-chats"), children: [showNewChat ? (_jsxs("button", { type: "button", className: "flex h-7 w-[calc(100%-0.5rem)] items-center gap-2 rounded-md px-2 text-sm text-sidebar-foreground/80 transition-colors hover:bg-sidebar-accent hover:text-sidebar-accent-foreground", onClick: () => void handleNewChat(), children: [_jsx(IconPlus, { size: 16, className: "shrink-0", "aria-hidden": "true" }), _jsx("span", { children: "New chat" })] })) : null, prelude, _jsx("div", { className: "flex justify-end px-2 pt-0.5", children: _jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsx("button", { type: "button", "data-dispatch-chat-source-toggle": true, "aria-pressed": includeExternal, "aria-label": includeExternal
|
|
270
421
|
? t("dispatch.sidebar.showLocalChats", {
|
|
271
422
|
defaultValue: "Show local chats",
|
|
272
423
|
})
|
|
@@ -278,9 +429,33 @@ function DispatchChatsSection({ onNavigate }) {
|
|
|
278
429
|
})
|
|
279
430
|
: t("dispatch.sidebar.showAllChats", {
|
|
280
431
|
defaultValue: "Show all chats",
|
|
281
|
-
}) })] }) }),
|
|
432
|
+
}) })] }) }), !chatFirstMode &&
|
|
433
|
+
chatsLoading &&
|
|
282
434
|
visibleThreads.length === 0 &&
|
|
283
|
-
Array.from({ length: 3 }).map((_, index) => (_jsxs("div", { className: "flex items-center gap-2 px-3 py-1", children: [_jsx(Skeleton, { className: "size-3.5 shrink-0 rounded-sm" }), _jsx(Skeleton, { className: "h-3 w-3/4 rounded" })] }, `chat-skeleton-${index}`))), _jsx(
|
|
435
|
+
Array.from({ length: 3 }).map((_, index) => (_jsxs("div", { className: "flex items-center gap-2 px-3 py-1", children: [_jsx(Skeleton, { className: "size-3.5 shrink-0 rounded-sm" }), _jsx(Skeleton, { className: "h-3 w-3/4 rounded" })] }, `chat-skeleton-${index}`))), chatFirstMode ? (_jsx(ChatFirstChatHistory, { items: chatItems, activeId: displayedActiveThreadId, loading: chatsLoading && visibleThreads.length === 0, loadingLabel: _jsx("div", { className: "space-y-1 px-2 py-1", children: [0, 1, 2].map((index) => (_jsxs("div", { className: "flex items-center gap-2 px-1 py-1", children: [_jsx(Skeleton, { className: "size-3.5 shrink-0 rounded-sm" }), _jsx(Skeleton, { className: "h-3 w-3/4 rounded" })] }, index))) }), label: t("dispatch.sidebar.chats", { defaultValue: "Chats" }), onSelect: (threadId) => openThread(threadId), renameMaxLength: 160, onRename: (threadId, title) => void renameThread(threadId, title), labels: {
|
|
436
|
+
options: (item) => t("dispatch.sidebar.chatOptions", {
|
|
437
|
+
title: item.titleText ?? "",
|
|
438
|
+
}),
|
|
439
|
+
renameInput: (item) => t("dispatch.sidebar.renameThread", {
|
|
440
|
+
title: item.titleText ?? "",
|
|
441
|
+
}),
|
|
442
|
+
rename: t("dispatch.sidebar.renameChat"),
|
|
443
|
+
}, renderAdditionalRowActions: (item, closeMenu) => (_jsxs(_Fragment, { children: [_jsxs("button", { type: "button", role: "menuitem", className: "an-chat-history-row__menu-item", onClick: () => {
|
|
444
|
+
closeMenu();
|
|
445
|
+
void writeClipboardText(item.id).then((copied) => {
|
|
446
|
+
toast[copied ? "success" : "error"](copied
|
|
447
|
+
? "Session ID copied"
|
|
448
|
+
: "Could not copy the session ID");
|
|
449
|
+
});
|
|
450
|
+
}, children: [_jsx(IconCopy, { size: 13, strokeWidth: 1.8 }), _jsx("span", { children: "Copy session ID" })] }), !chatFirstEmbedded ? (_jsxs("button", { type: "button", role: "menuitem", className: "an-chat-history-row__menu-item", onClick: () => {
|
|
451
|
+
closeMenu();
|
|
452
|
+
emitChatFirstSessionWatch({
|
|
453
|
+
sessionId: item.id,
|
|
454
|
+
title: item.titleText,
|
|
455
|
+
kind: "agent-chat",
|
|
456
|
+
sourceSessionId: displayedActiveThreadId ?? undefined,
|
|
457
|
+
});
|
|
458
|
+
}, children: [_jsx(IconEye, { size: 13, strokeWidth: 1.8 }), _jsx("span", { children: "Watch and message session" })] })) : null] })), className: "min-w-0" })) : (_jsx(ChatHistoryRail, { items: chatItems, activeId: displayedActiveThreadId, onSelect: (threadId) => openThread(threadId), onNewChat: () => void handleNewChat(), railLabels: {
|
|
284
459
|
newChat: t("dispatch.sidebar.newChat"),
|
|
285
460
|
showMore: t("dispatch.sidebar.chats"),
|
|
286
461
|
showLess: t("dispatch.sidebar.chats"),
|
|
@@ -292,10 +467,26 @@ function DispatchChatsSection({ onNavigate }) {
|
|
|
292
467
|
title: item.titleText ?? "",
|
|
293
468
|
}),
|
|
294
469
|
rename: t("dispatch.sidebar.renameChat"),
|
|
295
|
-
}, className: "
|
|
470
|
+
}, renderAdditionalRowActions: (item, closeMenu) => (_jsxs(_Fragment, { children: [_jsxs("button", { type: "button", role: "menuitem", className: "an-chat-history-row__menu-item", onClick: () => {
|
|
471
|
+
closeMenu();
|
|
472
|
+
void writeClipboardText(item.id).then((copied) => {
|
|
473
|
+
toast[copied ? "success" : "error"](copied
|
|
474
|
+
? "Session ID copied"
|
|
475
|
+
: "Could not copy the session ID");
|
|
476
|
+
});
|
|
477
|
+
}, children: [_jsx(IconCopy, { size: 13, strokeWidth: 1.8 }), _jsx("span", { children: "Copy session ID" })] }), chatFirstMode && !chatFirstEmbedded ? (_jsxs("button", { type: "button", role: "menuitem", className: "an-chat-history-row__menu-item", onClick: () => {
|
|
478
|
+
closeMenu();
|
|
479
|
+
emitChatFirstSessionWatch({
|
|
480
|
+
sessionId: item.id,
|
|
481
|
+
title: item.titleText,
|
|
482
|
+
kind: "agent-chat",
|
|
483
|
+
sourceSessionId: displayedActiveThreadId ?? undefined,
|
|
484
|
+
});
|
|
485
|
+
}, children: [_jsx(IconEye, { size: 13, strokeWidth: 1.8 }), _jsx("span", { children: "Watch and message session" })] })) : null] })), className: "min-w-0" }))] }));
|
|
296
486
|
}
|
|
297
|
-
export function NavContent({ onNavigate, extensions, collapsed = false, collapsible = false, onCollapsedChange, }) {
|
|
487
|
+
export function NavContent({ onNavigate, extensions, chatFirstMode = false, chatFirstEmbedded = false, collapsed = false, collapsible = false, onCollapsedChange, chatFirstAppLayout, onChatFirstAppLayoutChange, chatFirstApps = [], chatFirstAppsLoading = false, chatFirstAppsError, chatFirstActiveAppId, onChatFirstAppOpen, onChatFirstAppsRetry, }) {
|
|
298
488
|
const t = useT();
|
|
489
|
+
const chatFirstCopy = useMemo(() => createDispatchChatFirstCopy(t), [t]);
|
|
299
490
|
const location = useLocation();
|
|
300
491
|
const navigate = useNavigate();
|
|
301
492
|
const extensionNavItems = extensions?.navItems ?? EMPTY_NAV_ITEMS;
|
|
@@ -317,6 +508,18 @@ export function NavContent({ onNavigate, extensions, collapsed = false, collapsi
|
|
|
317
508
|
: t("sidebar.collapseSidebar"), className: "flex h-8 w-8 shrink-0 items-center justify-center rounded-md text-sidebar-foreground/65 transition-colors hover:bg-sidebar-accent hover:text-sidebar-accent-foreground", children: collapsed ? (_jsx(IconLayoutSidebarLeftExpand, { className: "h-4 w-4 rtl:-scale-x-100" })) : (_jsx(IconLayoutSidebarLeftCollapse, { className: "h-4 w-4 rtl:-scale-x-100" })) }) }), _jsx(TooltipContent, { side: "right", children: collapsed ? t("sidebar.expandSidebar") : t("sidebar.collapseSidebar") })] })) : null;
|
|
318
509
|
const searchButton = (_jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsx("button", { type: "button", onClick: openCommandMenu, "aria-label": t("sidebar.search"), className: "flex h-8 w-8 items-center justify-center rounded-md text-sidebar-foreground/65 transition-colors hover:bg-sidebar-accent hover:text-sidebar-accent-foreground", children: _jsx(IconSearch, { className: "h-4 w-4" }) }) }), _jsx(TooltipContent, { side: "right", children: t("sidebar.search") })] }));
|
|
319
510
|
const feedbackButton = (_jsx(FeedbackButton, { variant: collapsed ? "icon" : "sidebar", side: "right", className: collapsed ? "size-8" : "min-w-0" }));
|
|
511
|
+
const chatFirstCreateAppTrigger = (_jsx(CreateAppPopover, { align: "start", trigger: _jsx("button", { type: "button", className: "flex size-6 items-center justify-center rounded text-sidebar-foreground/55 hover:bg-sidebar-accent hover:text-sidebar-foreground", "aria-label": chatFirstCopy("createWorkspaceApp"), title: chatFirstCopy("createWorkspaceApp"), children: _jsx(IconPlus, { size: 14, "aria-hidden": "true" }) }) }));
|
|
512
|
+
const chatFirstPrimaryNavigation = (_jsx(ChatFirstPrimaryNavigation, { copy: chatFirstCopy, onOpenIntegrations: () => {
|
|
513
|
+
navigate(dispatchNavLinkTarget("/admin/integrations"));
|
|
514
|
+
onNavigate?.();
|
|
515
|
+
}, onOpenScheduled: () => {
|
|
516
|
+
navigate(dispatchNavLinkTarget("/admin/automations"));
|
|
517
|
+
onNavigate?.();
|
|
518
|
+
} }));
|
|
519
|
+
const chatFirstAppsRail = (_jsx(ChatFirstAppsRail, { apps: chatFirstApps, activeAppId: chatFirstActiveAppId, collapsed: collapsed, loading: chatFirstAppsLoading, error: chatFirstAppsError, layout: chatFirstAppLayout, onLayoutChange: onChatFirstAppLayoutChange, onRetry: onChatFirstAppsRetry, onOpenApp: (app) => {
|
|
520
|
+
onChatFirstAppOpen?.(app);
|
|
521
|
+
onNavigate?.();
|
|
522
|
+
}, createAppTrigger: chatFirstCreateAppTrigger, renderIcon: (app) => (_jsx(AppIcon, { id: app.id, name: app.name, size: "sm", className: "size-5 rounded-md" })), copy: chatFirstCopy }));
|
|
320
523
|
const renderNavItem = (item) => {
|
|
321
524
|
const Icon = item.icon;
|
|
322
525
|
const itemMatchesLocalPath = navItemMatchesPath(item, localPathname);
|
|
@@ -351,9 +554,9 @@ export function NavContent({ onNavigate, extensions, collapsed = false, collapsi
|
|
|
351
554
|
onNavigate?.();
|
|
352
555
|
}, className: cn("flex h-8 w-full items-center gap-2 rounded-md px-2 text-sm", itemMatchesLocalPath
|
|
353
556
|
? "bg-sidebar-accent font-medium text-sidebar-accent-foreground"
|
|
354
|
-
: "text-sidebar-foreground/70 hover:bg-sidebar-accent hover:text-sidebar-accent-foreground"), children: [Icon ? (_jsx(Icon, { size: 16, className: "shrink-0" })) : (_jsx("span", { className: "h-4 w-4 shrink-0", "aria-hidden": "true" })), _jsx("span", { className: "truncate", children: label })] })), !collapsed && item.id === "chat" && itemMatchesLocalPath ? (_jsx(DispatchChatsSection, { onNavigate: onNavigate })) : null] }, item.id));
|
|
557
|
+
: "text-sidebar-foreground/70 hover:bg-sidebar-accent hover:text-sidebar-accent-foreground"), children: [Icon ? (_jsx(Icon, { size: 16, className: "shrink-0" })) : (_jsx("span", { className: "h-4 w-4 shrink-0", "aria-hidden": "true" })), _jsx("span", { className: "truncate", children: label })] })), !collapsed && item.id === "chat" && itemMatchesLocalPath ? (_jsx(DispatchChatsSection, { onNavigate: onNavigate, chatFirstMode: chatFirstMode, chatFirstEmbedded: chatFirstEmbedded })) : null] }, item.id));
|
|
355
558
|
};
|
|
356
|
-
return (_jsxs(_Fragment, { children: [_jsx("div", { className: cn("flex h-12 shrink-0 items-center border-b border-sidebar-border", collapsed ? "justify-center px-0" : "px-4"), children: _jsxs("div", { className: cn("flex items-center", collapsed ? "justify-center" : "gap-2"), children: [_jsx("img", { src: appPath("/agent-native-icon-light.svg"), alt: "", "aria-hidden": "true", width: 35, height: 20, className: cn("block shrink-0 object-contain object-center dark:hidden", collapsed ? "h-4 w-7" : "h-5 w-[35px]") }), _jsx("img", { src: appPath("/agent-native-icon-dark.svg"), alt: "", "aria-hidden": "true", width: 35, height: 20, className: cn("hidden shrink-0 object-contain object-center dark:block", collapsed ? "h-4 w-7" : "h-5 w-[35px]") }), !collapsed && (_jsx("div", { className: "min-w-0 flex-1", children: _jsx("div", { "data-dispatch-sidebar-label": true, className: "truncate text-lg font-bold tracking-tight text-foreground", children: DISPATCH_SIDEBAR_LABEL }) }))] }) }), _jsxs("div", { className: "flex min-h-0 flex-1 flex-col overflow-y-auto", children: [_jsxs("nav", { className: cn("py-2", collapsed ? "px-1.5" : "px-2"), children: [_jsx("ul", { className: cn(collapsed ? "flex flex-col items-center gap-1" : "space-y-0.5"), children: primaryNavItems.map(renderNavItem) }), _jsx(WorkspaceAppsRail, { collapsed: collapsed, onNavigate: onNavigate })] }), _jsxs("div", { className: "mt-auto shrink-0", children: [_jsx("nav", { className: cn("py-1", collapsed ? "px-1.5" : "px-2"), children: _jsx("ul", { className: cn(collapsed ? "flex flex-col items-center gap-1" : "space-y-0.5"), children: BOTTOM_NAV_ITEMS.map(renderNavItem) }) }), _jsx("div", { className: cn("py-2", collapsed ? "flex justify-center px-1" : "px-3"), children: _jsx(OrgSwitcher, { compact: collapsed, reserveSpace: true }) })] }), _jsx(SidebarFooterActions, { collapsed: collapsed, feedback: feedbackButton, search: searchButton, collapse: collapseButton })] })] }));
|
|
559
|
+
return (_jsxs(_Fragment, { children: [_jsx("div", { className: cn("flex h-12 shrink-0 items-center border-b border-sidebar-border", collapsed ? "justify-center px-0" : "px-4"), children: _jsxs("div", { className: cn("flex items-center", collapsed ? "justify-center" : "gap-2"), children: [_jsx("img", { src: appPath("/agent-native-icon-light.svg"), alt: "", "aria-hidden": "true", width: 35, height: 20, className: cn("block shrink-0 object-contain object-center dark:hidden", collapsed ? "h-4 w-7" : "h-5 w-[35px]") }), _jsx("img", { src: appPath("/agent-native-icon-dark.svg"), alt: "", "aria-hidden": "true", width: 35, height: 20, className: cn("hidden shrink-0 object-contain object-center dark:block", collapsed ? "h-4 w-7" : "h-5 w-[35px]") }), !collapsed && (_jsx("div", { className: "min-w-0 flex-1", children: _jsx("div", { "data-dispatch-sidebar-label": true, className: "truncate text-lg font-bold tracking-tight text-foreground", children: DISPATCH_SIDEBAR_LABEL }) }))] }) }), chatFirstMode ? (_jsx("div", { className: "flex min-h-0 flex-1 flex-col overflow-y-auto", children: !collapsed ? (_jsx(DispatchChatsSection, { onNavigate: onNavigate, showNewChat: true, chatFirstMode: true, prelude: _jsxs(_Fragment, { children: [_jsx("nav", { className: "space-y-0.5 px-2 py-2", children: chatFirstPrimaryNavigation }), chatFirstAppsRail] }) })) : (chatFirstAppsRail) })) : null, _jsxs("div", { className: cn("flex min-h-0 flex-1 flex-col overflow-y-auto", chatFirstMode && "hidden"), children: [_jsxs("nav", { className: cn("py-2", collapsed ? "px-1.5" : "px-2"), children: [_jsx("ul", { className: cn(collapsed ? "flex flex-col items-center gap-1" : "space-y-0.5"), children: primaryNavItems.map(renderNavItem) }), _jsx(WorkspaceAppsRail, { collapsed: collapsed, onNavigate: onNavigate })] }), _jsxs("div", { className: "mt-auto shrink-0", children: [_jsx("nav", { className: cn("py-1", collapsed ? "px-1.5" : "px-2"), children: _jsx("ul", { className: cn(collapsed ? "flex flex-col items-center gap-1" : "space-y-0.5"), children: BOTTOM_NAV_ITEMS.map(renderNavItem) }) }), _jsx("div", { className: cn("py-2", collapsed ? "flex justify-center px-1" : "px-3"), children: _jsx(OrgSwitcher, { compact: collapsed, reserveSpace: true }) })] }), _jsx(SidebarFooterActions, { collapsed: collapsed, feedback: feedbackButton, search: searchButton, collapse: collapseButton })] }), chatFirstMode && collapsed ? (_jsx("div", { className: "mt-auto shrink-0", children: _jsx(SidebarFooterActions, { collapsed: true, feedback: feedbackButton, search: searchButton, collapse: collapseButton }) })) : null] }));
|
|
357
560
|
}
|
|
358
561
|
export function Layout({ children, extensions, agentPageHref, }) {
|
|
359
562
|
const t = useT();
|
|
@@ -372,7 +575,181 @@ export function Layout({ children, extensions, agentPageHref, }) {
|
|
|
372
575
|
});
|
|
373
576
|
const localPathname = localDispatchPath(location.pathname);
|
|
374
577
|
const isChatRoute = localPathname === "/chat" || localPathname.startsWith("/chat/");
|
|
578
|
+
const chatFirstSurfaceScope = threadIdFromPath(localPathname) ?? "new";
|
|
375
579
|
const isWorkspaceAppHostRoute = localPathname.startsWith("/apps/");
|
|
580
|
+
const [chatFirstPreference, setChatFirstPreference] = useState(() => readChatFirstMode());
|
|
581
|
+
const chatFirstEmbedded = typeof window !== "undefined" &&
|
|
582
|
+
new URLSearchParams(window.location.search).get("chatFirst") === "1";
|
|
583
|
+
const chatFirstMode = extensions?.chatFirst === true || chatFirstPreference || chatFirstEmbedded;
|
|
584
|
+
const [chatFirstAppLayout, setChatFirstAppLayout] = useState(() => readChatFirstAppLayout());
|
|
585
|
+
const chatFirstAppLayoutHydratedRef = useRef(false);
|
|
586
|
+
const chatFirstAppsQuery = useActionQuery("list-workspace-apps", { includeAgentCards: false }, { enabled: chatFirstMode && isChatRoute });
|
|
587
|
+
const chatFirstWorkspaceApps = useMemo(() => mergeChatFirstWorkspaceApps(chatFirstAppsQuery.data), [chatFirstAppsQuery.data]);
|
|
588
|
+
const chatFirstAppRegistrations = useMemo(() => chatFirstWorkspaceApps.map((app) => ({
|
|
589
|
+
id: app.id,
|
|
590
|
+
name: app.name,
|
|
591
|
+
path: app.path,
|
|
592
|
+
url: app.url,
|
|
593
|
+
enabled: app.status !== "pending" && app.archived !== true,
|
|
594
|
+
})), [chatFirstWorkspaceApps]);
|
|
595
|
+
const chatFirstAppItems = useMemo(() => chatFirstWorkspaceApps.map((app) => ({
|
|
596
|
+
id: app.id,
|
|
597
|
+
name: app.name,
|
|
598
|
+
})), [chatFirstWorkspaceApps]);
|
|
599
|
+
const chatFirstCopy = useMemo(() => createDispatchChatFirstCopy(t), [t]);
|
|
600
|
+
const createChatFirstEmbedSession = useActionMutation("create_embed_session", { skipActionQueryInvalidation: true });
|
|
601
|
+
const [chatFirstPane, setChatFirstPane] = useState(null);
|
|
602
|
+
const [chatFirstEmbedUrl, setChatFirstEmbedUrl] = useState(null);
|
|
603
|
+
const [chatFirstEmbedError, setChatFirstEmbedError] = useState(null);
|
|
604
|
+
const [chatFirstEmbedAttempt, setChatFirstEmbedAttempt] = useState(0);
|
|
605
|
+
const [chatFirstNotice, setChatFirstNotice] = useState(null);
|
|
606
|
+
const chatFirstSessionWatch = useChatFirstSessionWatch();
|
|
607
|
+
const chatFirstSurfaceTabs = useChatFirstSurfaceTabs(chatFirstSurfaceScope);
|
|
608
|
+
const chatFirstSurfaceTabsStore = getChatFirstSurfaceTabsStore(chatFirstSurfaceScope);
|
|
609
|
+
const chatFirstAgentsQuery = useActionQuery("search-agent-threads", { sourceId: "current", limit: 12 }, {
|
|
610
|
+
enabled: chatFirstMode &&
|
|
611
|
+
isChatRoute &&
|
|
612
|
+
chatFirstSurfaceTabs.activeTabId?.startsWith("agents:") === true,
|
|
613
|
+
});
|
|
614
|
+
const chatFirstSurfacePanel = useChatFirstSurfacePanel(chatFirstSurfaceScope);
|
|
615
|
+
const { setOpen: setChatFirstSurfacePanelOpen } = chatFirstSurfacePanel;
|
|
616
|
+
const chatFirstSurfaceResize = useChatFirstSurfaceResize(chatFirstSurfaceScope);
|
|
617
|
+
const chatFirstPaneHydratedRef = useRef(false);
|
|
618
|
+
const pendingChatFirstOpenAppRef = useRef(null);
|
|
619
|
+
const previousChatFirstSurfaceScopeRef = useRef(chatFirstSurfaceScope);
|
|
620
|
+
const previousChatFirstSurfaceTabCountRef = useRef(null);
|
|
621
|
+
const activeChatFirstSurfaceTab = useMemo(() => chatFirstSurfaceTabs.tabs.find((tab) => tab.id === chatFirstSurfaceTabs.activeTabId) ?? null, [chatFirstSurfaceTabs]);
|
|
622
|
+
const activeChatFirstApp = useMemo(() => activeChatFirstSurfaceTab?.kind === "app" &&
|
|
623
|
+
activeChatFirstSurfaceTab.appId
|
|
624
|
+
? (chatFirstWorkspaceApps.find((app) => app.id === activeChatFirstSurfaceTab.appId) ?? null)
|
|
625
|
+
: null, [activeChatFirstSurfaceTab, chatFirstWorkspaceApps]);
|
|
626
|
+
const chatFirstAgentActivities = useMemo(() => (chatFirstAgentsQuery.data?.threads ?? []).map((thread) => ({
|
|
627
|
+
sessionId: thread.id,
|
|
628
|
+
title: thread.title || chatFirstCopy("agentsTitle", { name: thread.id }),
|
|
629
|
+
subtitle: thread.snippet || thread.preview || chatFirstCopy("session"),
|
|
630
|
+
status: "recent",
|
|
631
|
+
...(thread.updatedAt ? { updatedAt: thread.updatedAt } : {}),
|
|
632
|
+
})), [chatFirstAgentsQuery.data, chatFirstCopy]);
|
|
633
|
+
const chatFirstEmbedPath = activeChatFirstSurfaceTab?.kind === "app"
|
|
634
|
+
? (activeChatFirstSurfaceTab.path ??
|
|
635
|
+
chatFirstPane?.path ??
|
|
636
|
+
activeChatFirstApp?.path)
|
|
637
|
+
: null;
|
|
638
|
+
useEffect(() => {
|
|
639
|
+
if (!chatFirstMode || !isChatRoute || !activeChatFirstApp) {
|
|
640
|
+
setChatFirstEmbedUrl(null);
|
|
641
|
+
setChatFirstEmbedError(null);
|
|
642
|
+
return;
|
|
643
|
+
}
|
|
644
|
+
if (!chatFirstEmbedPath?.startsWith("/")) {
|
|
645
|
+
setChatFirstEmbedUrl(null);
|
|
646
|
+
setChatFirstEmbedError(chatFirstCopy("appUnavailable"));
|
|
647
|
+
return;
|
|
648
|
+
}
|
|
649
|
+
let cancelled = false;
|
|
650
|
+
setChatFirstEmbedUrl(null);
|
|
651
|
+
setChatFirstEmbedError(null);
|
|
652
|
+
void createChatFirstEmbedSession
|
|
653
|
+
.mutateAsync(buildChatFirstEmbedSessionInput(activeChatFirstApp.id, chatFirstEmbedPath))
|
|
654
|
+
.then((result) => {
|
|
655
|
+
if (!cancelled)
|
|
656
|
+
setChatFirstEmbedUrl(result.startUrl);
|
|
657
|
+
})
|
|
658
|
+
.catch((cause) => {
|
|
659
|
+
if (!cancelled) {
|
|
660
|
+
setChatFirstEmbedError(cause instanceof Error
|
|
661
|
+
? cause.message
|
|
662
|
+
: chatFirstCopy("appUnavailable"));
|
|
663
|
+
}
|
|
664
|
+
});
|
|
665
|
+
return () => {
|
|
666
|
+
cancelled = true;
|
|
667
|
+
};
|
|
668
|
+
}, [
|
|
669
|
+
activeChatFirstApp,
|
|
670
|
+
chatFirstCopy,
|
|
671
|
+
chatFirstEmbedAttempt,
|
|
672
|
+
chatFirstEmbedPath,
|
|
673
|
+
chatFirstMode,
|
|
674
|
+
createChatFirstEmbedSession.mutateAsync,
|
|
675
|
+
isChatRoute,
|
|
676
|
+
]);
|
|
677
|
+
const persistChatFirstPane = useCallback((pane) => {
|
|
678
|
+
setChatFirstPane(pane);
|
|
679
|
+
void writeClientAppState(CHAT_FIRST_PANE_STATE_KEY, pane).catch(() => {
|
|
680
|
+
setChatFirstNotice("The app pane opened locally, but its focus could not be synced.");
|
|
681
|
+
});
|
|
682
|
+
}, []);
|
|
683
|
+
const openChatFirstPane = useCallback((pane) => {
|
|
684
|
+
setChatFirstNotice(null);
|
|
685
|
+
closeChatFirstSessionWatch();
|
|
686
|
+
const app = chatFirstAppRegistrations.find((candidate) => candidate.id === pane.appId);
|
|
687
|
+
chatFirstSurfaceTabsStore.open({
|
|
688
|
+
id: chatFirstSurfaceTabId("app", `${pane.appId}:${pane.path ?? pane.view ?? "/"}`),
|
|
689
|
+
kind: "app",
|
|
690
|
+
title: app?.name ?? pane.appId,
|
|
691
|
+
appId: pane.appId,
|
|
692
|
+
...(pane.path ? { path: pane.path } : {}),
|
|
693
|
+
...(pane.view ? { view: pane.view } : {}),
|
|
694
|
+
});
|
|
695
|
+
persistChatFirstPane(pane);
|
|
696
|
+
}, [
|
|
697
|
+
chatFirstAppRegistrations,
|
|
698
|
+
chatFirstSurfaceTabsStore,
|
|
699
|
+
persistChatFirstPane,
|
|
700
|
+
]);
|
|
701
|
+
const openChatFirstSurface = useCallback((kind) => {
|
|
702
|
+
if (kind !== "agents")
|
|
703
|
+
return;
|
|
704
|
+
persistChatFirstPane(null);
|
|
705
|
+
closeChatFirstSessionWatch();
|
|
706
|
+
chatFirstSurfaceTabsStore.open({
|
|
707
|
+
id: chatFirstSurfaceTabId("agents", "activity"),
|
|
708
|
+
kind: "agents",
|
|
709
|
+
title: "Agents",
|
|
710
|
+
});
|
|
711
|
+
}, [chatFirstSurfaceTabsStore, persistChatFirstPane]);
|
|
712
|
+
const resolveChatFirstOpenBrowser = useCallback((detail) => {
|
|
713
|
+
const resolution = resolveChatFirstBrowserTarget(detail);
|
|
714
|
+
if (resolution.status === "unresolved") {
|
|
715
|
+
setChatFirstNotice(chatFirstBrowserResolutionMessage(resolution.reason));
|
|
716
|
+
return;
|
|
717
|
+
}
|
|
718
|
+
persistChatFirstPane(null);
|
|
719
|
+
closeChatFirstSessionWatch();
|
|
720
|
+
setChatFirstNotice(null);
|
|
721
|
+
chatFirstSurfaceTabsStore.open({
|
|
722
|
+
id: chatFirstSurfaceTabId("browser", resolution.target.url),
|
|
723
|
+
kind: "browser",
|
|
724
|
+
title: resolution.target.title ?? "Browser",
|
|
725
|
+
url: resolution.target.url,
|
|
726
|
+
});
|
|
727
|
+
}, [chatFirstSurfaceTabsStore, persistChatFirstPane]);
|
|
728
|
+
const resolveChatFirstOpenApp = useCallback((detail) => {
|
|
729
|
+
if (chatFirstAppsQuery.isLoading) {
|
|
730
|
+
pendingChatFirstOpenAppRef.current = detail;
|
|
731
|
+
return;
|
|
732
|
+
}
|
|
733
|
+
if (chatFirstAppsQuery.isError) {
|
|
734
|
+
pendingChatFirstOpenAppRef.current = null;
|
|
735
|
+
setChatFirstNotice("Workspace apps could not be loaded, so the requested app was not opened.");
|
|
736
|
+
return;
|
|
737
|
+
}
|
|
738
|
+
const resolution = resolveChatFirstAppTarget(detail, chatFirstAppRegistrations, {
|
|
739
|
+
currentOrigin: typeof window === "undefined" ? undefined : window.location.origin,
|
|
740
|
+
});
|
|
741
|
+
pendingChatFirstOpenAppRef.current = null;
|
|
742
|
+
if (resolution.status === "unresolved") {
|
|
743
|
+
setChatFirstNotice(chatFirstResolutionMessage(resolution.reason));
|
|
744
|
+
return;
|
|
745
|
+
}
|
|
746
|
+
openChatFirstPane(resolution.target);
|
|
747
|
+
}, [
|
|
748
|
+
chatFirstAppRegistrations,
|
|
749
|
+
chatFirstAppsQuery.isError,
|
|
750
|
+
chatFirstAppsQuery.isLoading,
|
|
751
|
+
openChatFirstPane,
|
|
752
|
+
]);
|
|
376
753
|
const sidebarBeforeAppRef = useRef(null);
|
|
377
754
|
const sidebarAutoCollapsedRef = useRef(false);
|
|
378
755
|
const chatHomeHandoffActive = useAgentChatHomeHandoff({
|
|
@@ -386,6 +763,194 @@ export function Layout({ children, extensions, agentPageHref, }) {
|
|
|
386
763
|
requireActiveHandoff: true,
|
|
387
764
|
};
|
|
388
765
|
useAgentChatHomeHandoffLinks(chatHandoffLinkOptions);
|
|
766
|
+
useEffect(() => {
|
|
767
|
+
const handleModeChange = (event) => {
|
|
768
|
+
const enabled = event.detail
|
|
769
|
+
?.enabled;
|
|
770
|
+
setChatFirstPreference(enabled === true);
|
|
771
|
+
};
|
|
772
|
+
window.addEventListener(CHAT_FIRST_MODE_CHANGED_EVENT, handleModeChange);
|
|
773
|
+
return () => window.removeEventListener(CHAT_FIRST_MODE_CHANGED_EVENT, handleModeChange);
|
|
774
|
+
}, []);
|
|
775
|
+
useEffect(() => {
|
|
776
|
+
if (!chatFirstMode ||
|
|
777
|
+
!isChatRoute ||
|
|
778
|
+
chatFirstAppLayoutHydratedRef.current) {
|
|
779
|
+
return;
|
|
780
|
+
}
|
|
781
|
+
chatFirstAppLayoutHydratedRef.current = true;
|
|
782
|
+
void readClientAppState("chat-first-app-layout")
|
|
783
|
+
.then((value) => {
|
|
784
|
+
if (!value || typeof value !== "object")
|
|
785
|
+
return;
|
|
786
|
+
const candidate = value;
|
|
787
|
+
const ids = (input) => Array.isArray(input)
|
|
788
|
+
? input.filter((id) => typeof id === "string" && id.trim().length > 0)
|
|
789
|
+
: [];
|
|
790
|
+
setChatFirstAppLayout({
|
|
791
|
+
pinnedIds: [...new Set(ids(candidate.pinnedIds))],
|
|
792
|
+
orderedIds: [...new Set(ids(candidate.orderedIds))],
|
|
793
|
+
});
|
|
794
|
+
})
|
|
795
|
+
.catch(() => {
|
|
796
|
+
// Device-local layout remains the fallback when workspace state is unavailable.
|
|
797
|
+
});
|
|
798
|
+
}, [chatFirstMode, isChatRoute]);
|
|
799
|
+
const persistChatFirstAppLayout = useCallback((layout) => {
|
|
800
|
+
setChatFirstAppLayout(layout);
|
|
801
|
+
void writeClientAppState("chat-first-app-layout", layout).catch(() => {
|
|
802
|
+
setChatFirstNotice("App order changed locally, but workspace state could not be synced.");
|
|
803
|
+
});
|
|
804
|
+
}, []);
|
|
805
|
+
useEffect(() => {
|
|
806
|
+
if (!chatFirstMode || !isChatRoute) {
|
|
807
|
+
setChatFirstPane(null);
|
|
808
|
+
closeChatFirstSessionWatch();
|
|
809
|
+
chatFirstSurfaceTabsStore.closeAll();
|
|
810
|
+
setChatFirstNotice(null);
|
|
811
|
+
pendingChatFirstOpenAppRef.current = null;
|
|
812
|
+
chatFirstPaneHydratedRef.current = false;
|
|
813
|
+
return;
|
|
814
|
+
}
|
|
815
|
+
const unsubscribeApp = subscribeChatFirstOpenApp(resolveChatFirstOpenApp);
|
|
816
|
+
const unsubscribeBrowser = subscribeChatFirstOpenBrowser(resolveChatFirstOpenBrowser);
|
|
817
|
+
return () => {
|
|
818
|
+
unsubscribeApp();
|
|
819
|
+
unsubscribeBrowser();
|
|
820
|
+
};
|
|
821
|
+
}, [
|
|
822
|
+
chatFirstMode,
|
|
823
|
+
isChatRoute,
|
|
824
|
+
chatFirstSurfaceTabsStore,
|
|
825
|
+
resolveChatFirstOpenApp,
|
|
826
|
+
resolveChatFirstOpenBrowser,
|
|
827
|
+
]);
|
|
828
|
+
useEffect(() => {
|
|
829
|
+
if (!chatFirstMode ||
|
|
830
|
+
!isChatRoute ||
|
|
831
|
+
chatFirstPaneHydratedRef.current ||
|
|
832
|
+
chatFirstAppsQuery.isLoading ||
|
|
833
|
+
chatFirstAppsQuery.isError) {
|
|
834
|
+
return;
|
|
835
|
+
}
|
|
836
|
+
chatFirstPaneHydratedRef.current = true;
|
|
837
|
+
if (chatFirstPane)
|
|
838
|
+
return;
|
|
839
|
+
let active = true;
|
|
840
|
+
void readClientAppState(CHAT_FIRST_PANE_STATE_KEY)
|
|
841
|
+
.then((value) => {
|
|
842
|
+
if (!active)
|
|
843
|
+
return;
|
|
844
|
+
const persisted = persistedChatFirstPane(value);
|
|
845
|
+
if (!persisted)
|
|
846
|
+
return;
|
|
847
|
+
const resolution = resolveChatFirstAppTarget({
|
|
848
|
+
app: persisted.appId,
|
|
849
|
+
path: persisted.path,
|
|
850
|
+
view: persisted.view,
|
|
851
|
+
}, chatFirstAppRegistrations, {
|
|
852
|
+
currentOrigin: typeof window === "undefined"
|
|
853
|
+
? undefined
|
|
854
|
+
: window.location.origin,
|
|
855
|
+
});
|
|
856
|
+
if (resolution.status === "ready")
|
|
857
|
+
openChatFirstPane(resolution.target);
|
|
858
|
+
})
|
|
859
|
+
.catch(() => {
|
|
860
|
+
if (active) {
|
|
861
|
+
setChatFirstNotice("The last app pane could not be restored from workspace state.");
|
|
862
|
+
}
|
|
863
|
+
});
|
|
864
|
+
return () => {
|
|
865
|
+
active = false;
|
|
866
|
+
};
|
|
867
|
+
}, [
|
|
868
|
+
chatFirstAppsQuery.isError,
|
|
869
|
+
chatFirstAppsQuery.isLoading,
|
|
870
|
+
chatFirstAppRegistrations,
|
|
871
|
+
chatFirstMode,
|
|
872
|
+
chatFirstPane,
|
|
873
|
+
isChatRoute,
|
|
874
|
+
openChatFirstPane,
|
|
875
|
+
]);
|
|
876
|
+
useEffect(() => {
|
|
877
|
+
if (previousChatFirstSurfaceScopeRef.current === chatFirstSurfaceScope) {
|
|
878
|
+
return;
|
|
879
|
+
}
|
|
880
|
+
previousChatFirstSurfaceScopeRef.current = chatFirstSurfaceScope;
|
|
881
|
+
persistChatFirstPane(null);
|
|
882
|
+
setChatFirstEmbedUrl(null);
|
|
883
|
+
setChatFirstEmbedError(null);
|
|
884
|
+
setChatFirstNotice(null);
|
|
885
|
+
pendingChatFirstOpenAppRef.current = null;
|
|
886
|
+
chatFirstPaneHydratedRef.current = true;
|
|
887
|
+
chatFirstSurfaceTabsStore.closeAll();
|
|
888
|
+
setChatFirstSurfacePanelOpen(false);
|
|
889
|
+
closeChatFirstSessionWatch();
|
|
890
|
+
}, [
|
|
891
|
+
chatFirstSurfaceScope,
|
|
892
|
+
chatFirstSurfaceTabsStore,
|
|
893
|
+
persistChatFirstPane,
|
|
894
|
+
setChatFirstSurfacePanelOpen,
|
|
895
|
+
]);
|
|
896
|
+
useEffect(() => {
|
|
897
|
+
const tabCount = chatFirstSurfaceTabs.tabs.length;
|
|
898
|
+
const previousTabCount = previousChatFirstSurfaceTabCountRef.current;
|
|
899
|
+
if (!chatFirstMode || !isChatRoute) {
|
|
900
|
+
setChatFirstSurfacePanelOpen(false);
|
|
901
|
+
}
|
|
902
|
+
else if (tabCount > 0 &&
|
|
903
|
+
(previousTabCount === null || previousTabCount === 0)) {
|
|
904
|
+
setChatFirstSurfacePanelOpen(true);
|
|
905
|
+
}
|
|
906
|
+
else if (tabCount === 0 &&
|
|
907
|
+
previousTabCount !== null &&
|
|
908
|
+
previousTabCount > 0) {
|
|
909
|
+
setChatFirstSurfacePanelOpen(false);
|
|
910
|
+
}
|
|
911
|
+
previousChatFirstSurfaceTabCountRef.current = tabCount;
|
|
912
|
+
}, [
|
|
913
|
+
chatFirstMode,
|
|
914
|
+
setChatFirstSurfacePanelOpen,
|
|
915
|
+
chatFirstSurfaceTabs.tabs.length,
|
|
916
|
+
isChatRoute,
|
|
917
|
+
]);
|
|
918
|
+
useEffect(() => {
|
|
919
|
+
const activeTab = activeChatFirstSurfaceTab;
|
|
920
|
+
if (activeTab?.kind === "side-chat" &&
|
|
921
|
+
activeTab.session &&
|
|
922
|
+
!chatFirstSessionWatch.target) {
|
|
923
|
+
emitChatFirstSessionWatch(activeTab.session);
|
|
924
|
+
}
|
|
925
|
+
}, [activeChatFirstSurfaceTab, chatFirstSessionWatch.target]);
|
|
926
|
+
useEffect(() => {
|
|
927
|
+
const pending = pendingChatFirstOpenAppRef.current;
|
|
928
|
+
if (!pending || chatFirstAppsQuery.isLoading)
|
|
929
|
+
return;
|
|
930
|
+
resolveChatFirstOpenApp(pending);
|
|
931
|
+
}, [
|
|
932
|
+
chatFirstAppsQuery.data,
|
|
933
|
+
chatFirstAppsQuery.isError,
|
|
934
|
+
chatFirstAppsQuery.isLoading,
|
|
935
|
+
resolveChatFirstOpenApp,
|
|
936
|
+
]);
|
|
937
|
+
useEffect(() => {
|
|
938
|
+
const target = chatFirstSessionWatch.target;
|
|
939
|
+
if (!target || !chatFirstMode || !isChatRoute)
|
|
940
|
+
return;
|
|
941
|
+
setChatFirstPane(null);
|
|
942
|
+
chatFirstSurfaceTabsStore.open({
|
|
943
|
+
id: chatFirstSurfaceTabId("side-chat", target.sessionId),
|
|
944
|
+
kind: "side-chat",
|
|
945
|
+
title: target.title ? `Watch · ${target.title}` : "Watched session",
|
|
946
|
+
session: target,
|
|
947
|
+
});
|
|
948
|
+
}, [
|
|
949
|
+
chatFirstMode,
|
|
950
|
+
chatFirstSessionWatch.target,
|
|
951
|
+
chatFirstSurfaceTabsStore,
|
|
952
|
+
isChatRoute,
|
|
953
|
+
]);
|
|
389
954
|
useEffect(() => {
|
|
390
955
|
if (isWorkspaceAppHostRoute) {
|
|
391
956
|
if (!sidebarAutoCollapsedRef.current) {
|
|
@@ -416,9 +981,114 @@ export function Layout({ children, extensions, agentPageHref, }) {
|
|
|
416
981
|
// Ignore storage failures; the in-memory preference still works.
|
|
417
982
|
}
|
|
418
983
|
}, [isWorkspaceAppHostRoute, sidebarCollapsed]);
|
|
984
|
+
const activateChatFirstSurfaceTab = useCallback((tab) => {
|
|
985
|
+
chatFirstSurfaceTabsStore.activate(tab.id);
|
|
986
|
+
if (tab.kind === "app" && tab.appId) {
|
|
987
|
+
closeChatFirstSessionWatch();
|
|
988
|
+
persistChatFirstPane({
|
|
989
|
+
appId: tab.appId,
|
|
990
|
+
...(tab.path ? { path: tab.path } : {}),
|
|
991
|
+
...(tab.view ? { view: tab.view } : {}),
|
|
992
|
+
});
|
|
993
|
+
return;
|
|
994
|
+
}
|
|
995
|
+
if (tab.kind === "browser" && tab.url) {
|
|
996
|
+
persistChatFirstPane(null);
|
|
997
|
+
closeChatFirstSessionWatch();
|
|
998
|
+
return;
|
|
999
|
+
}
|
|
1000
|
+
if (tab.kind === "side-chat" && tab.session) {
|
|
1001
|
+
persistChatFirstPane(null);
|
|
1002
|
+
emitChatFirstSessionWatch(tab.session);
|
|
1003
|
+
return;
|
|
1004
|
+
}
|
|
1005
|
+
if (tab.kind === "agents") {
|
|
1006
|
+
persistChatFirstPane(null);
|
|
1007
|
+
closeChatFirstSessionWatch();
|
|
1008
|
+
}
|
|
1009
|
+
}, [
|
|
1010
|
+
chatFirstSurfaceTabs.tabs,
|
|
1011
|
+
chatFirstSurfaceTabsStore,
|
|
1012
|
+
persistChatFirstPane,
|
|
1013
|
+
]);
|
|
1014
|
+
const closeChatFirstSurfaceTab = useCallback((tab) => {
|
|
1015
|
+
const isActive = chatFirstSurfaceTabs.activeTabId === tab.id;
|
|
1016
|
+
if (tab.kind === "app" && isActive)
|
|
1017
|
+
persistChatFirstPane(null);
|
|
1018
|
+
if (tab.kind === "side-chat" && isActive) {
|
|
1019
|
+
closeChatFirstSessionWatch();
|
|
1020
|
+
}
|
|
1021
|
+
chatFirstSurfaceTabsStore.close(tab.id);
|
|
1022
|
+
}, [chatFirstSurfaceTabs, chatFirstSurfaceTabsStore, persistChatFirstPane]);
|
|
1023
|
+
const closeAllChatFirstSurfaceTabs = useCallback(() => {
|
|
1024
|
+
persistChatFirstPane(null);
|
|
1025
|
+
closeChatFirstSessionWatch();
|
|
1026
|
+
chatFirstSurfaceTabsStore.closeAll();
|
|
1027
|
+
}, [chatFirstSurfaceTabsStore, persistChatFirstPane]);
|
|
1028
|
+
const renderChatFirstWatchChat = useCallback((target) => (_jsx(AgentChatSurface, { mode: "page", className: "h-full min-h-0 w-full", defaultMode: "chat", storageKey: `dispatch-session-watch:${target.sessionId}`, restoreActiveThread: false, threadUrlSync: {
|
|
1029
|
+
routeThreadId: target.sessionId,
|
|
1030
|
+
getPath: chatThreadPath,
|
|
1031
|
+
navigate: () => undefined,
|
|
1032
|
+
}, showHeader: false, showTabBar: false, showPageNewChatButton: false, chatOnly: true, dynamicSuggestions: false, suggestions: [], emptyStateDisplay: "hidden", composerPlaceholder: t("dispatch.pages.chatFirstSessionMessagePlaceholder") })), [t]);
|
|
1033
|
+
const renderChatFirstSurfaceTab = useCallback((tab) => {
|
|
1034
|
+
if (tab.kind === "app") {
|
|
1035
|
+
if (tab.id !== chatFirstSurfaceTabs.activeTabId)
|
|
1036
|
+
return null;
|
|
1037
|
+
const app = tab.appId
|
|
1038
|
+
? (chatFirstWorkspaceApps.find((candidate) => candidate.id === tab.appId) ?? null)
|
|
1039
|
+
: null;
|
|
1040
|
+
return (_jsx(ChatFirstAppPane, { app: app, status: chatFirstEmbedError
|
|
1041
|
+
? "error"
|
|
1042
|
+
: chatFirstEmbedUrl
|
|
1043
|
+
? "ready"
|
|
1044
|
+
: chatFirstAppsQuery.isLoading
|
|
1045
|
+
? "loading"
|
|
1046
|
+
: app
|
|
1047
|
+
? "loading"
|
|
1048
|
+
: "unresolved", embedUrl: chatFirstEmbedUrl, errorMessage: chatFirstEmbedError, onRetry: () => setChatFirstEmbedAttempt((value) => value + 1), renderEmbed: ({ url, title }) => (_jsx("iframe", { "data-dispatch-chat-first-app-frame": true, src: url, title: title ?? chatFirstCopy("appUnavailable"), referrerPolicy: "no-referrer", allow: "clipboard-read; clipboard-write", className: "h-full w-full border-0 bg-background" })), copy: chatFirstCopy }));
|
|
1049
|
+
}
|
|
1050
|
+
if (tab.kind === "browser" && tab.url) {
|
|
1051
|
+
return (_jsx(ChatFirstBrowserPane, { url: tab.url, title: tab.title, onClose: () => closeChatFirstSurfaceTab(tab), renderEmbed: ({ url, title, key }) => (_jsx("iframe", { src: url, title: title ?? chatFirstCopy("browserPage"), referrerPolicy: "no-referrer", allow: "clipboard-read; clipboard-write", className: "h-full w-full border-0 bg-background" }, key)), copy: chatFirstCopy }));
|
|
1052
|
+
}
|
|
1053
|
+
if (tab.kind === "side-chat") {
|
|
1054
|
+
const target = tab.session ??
|
|
1055
|
+
(tab.id === chatFirstSurfaceTabs.activeTabId
|
|
1056
|
+
? chatFirstSessionWatch.target
|
|
1057
|
+
: null);
|
|
1058
|
+
return target ? (_jsx(ChatFirstSessionWatchPane, { target: target, onClose: () => closeChatFirstSurfaceTab(tab), renderChat: renderChatFirstWatchChat, copy: chatFirstCopy })) : null;
|
|
1059
|
+
}
|
|
1060
|
+
if (tab.kind === "agents") {
|
|
1061
|
+
return (_jsx(ChatFirstAgentsPane, { activities: chatFirstAgentActivities, loading: chatFirstAgentsQuery.isLoading, error: chatFirstAgentsQuery.isError
|
|
1062
|
+
? chatFirstAgentsQuery.error.message
|
|
1063
|
+
: null, onRefresh: () => void chatFirstAgentsQuery.refetch(), onWatch: (activity) => emitChatFirstSessionWatch({
|
|
1064
|
+
sessionId: activity.sessionId,
|
|
1065
|
+
title: activity.title,
|
|
1066
|
+
kind: "agent-chat",
|
|
1067
|
+
...(activity.goalId ? { goalId: activity.goalId } : {}),
|
|
1068
|
+
}), copy: chatFirstCopy }));
|
|
1069
|
+
}
|
|
1070
|
+
return null;
|
|
1071
|
+
}, [
|
|
1072
|
+
chatFirstAgentActivities,
|
|
1073
|
+
chatFirstAgentsQuery.error,
|
|
1074
|
+
chatFirstAgentsQuery.isError,
|
|
1075
|
+
chatFirstAgentsQuery.isLoading,
|
|
1076
|
+
chatFirstAppsQuery.isLoading,
|
|
1077
|
+
chatFirstCopy,
|
|
1078
|
+
chatFirstEmbedError,
|
|
1079
|
+
chatFirstEmbedUrl,
|
|
1080
|
+
chatFirstSessionWatch.target,
|
|
1081
|
+
chatFirstSurfaceTabs.activeTabId,
|
|
1082
|
+
chatFirstWorkspaceApps,
|
|
1083
|
+
closeChatFirstSurfaceTab,
|
|
1084
|
+
renderChatFirstWatchChat,
|
|
1085
|
+
]);
|
|
419
1086
|
if (CHROMELESS_PATHS.some((path) => localPathname === path)) {
|
|
420
1087
|
return _jsx(_Fragment, { children: children });
|
|
421
1088
|
}
|
|
1089
|
+
if (isWorkspaceAppHostRoute) {
|
|
1090
|
+
return (_jsx(DispatchExtensionsContext.Provider, { value: extensions, children: _jsx(HeaderActionsProvider, { children: _jsx("div", { "data-dispatch-workspace-app-chrome-less": true, className: "h-screen w-full overflow-hidden bg-background", children: children }) }) }));
|
|
1091
|
+
}
|
|
422
1092
|
const showHeader = !isChatRoute && !pageOwnsToolbar(localPathname);
|
|
423
1093
|
function openAskAgentFullscreen() {
|
|
424
1094
|
focusAgentChat();
|
|
@@ -429,10 +1099,27 @@ export function Layout({ children, extensions, agentPageHref, }) {
|
|
|
429
1099
|
t("dispatch.sidebar.suggestionRouteSlack"),
|
|
430
1100
|
t("dispatch.sidebar.suggestionGrantKey"),
|
|
431
1101
|
];
|
|
432
|
-
const appContent = (_jsxs("div", { className: "flex h-full min-w-0 flex-1 flex-col overflow-hidden", children: [showHeader ? _jsx(Header, { onOpenMobile: () => setMobileOpen(true) }) : null, _jsx(InvitationBanner, {}), _jsx("main", { className: cn("flex-1", isChatRoute || isWorkspaceAppHostRoute
|
|
1102
|
+
const appContent = (_jsxs("div", { className: "relative flex h-full min-w-0 flex-1 flex-col overflow-hidden", children: [showHeader ? _jsx(Header, { onOpenMobile: () => setMobileOpen(true) }) : null, _jsx(InvitationBanner, {}), isChatRoute && chatFirstMode ? (_jsx(ChatFirstSurfacePanelToggle, { open: chatFirstSurfacePanel.open, onToggle: chatFirstSurfacePanel.toggle, className: "absolute right-3 top-2 z-[4]" })) : null, isChatRoute && chatFirstMode && chatFirstNotice ? (_jsxs("div", { className: "dispatch-chat-first-notice", role: "status", "aria-live": "polite", children: [_jsx("span", { children: chatFirstNotice }), _jsx("button", { type: "button", onClick: () => setChatFirstNotice(null), "aria-label": "Dismiss app notice", children: "Dismiss" })] })) : null, _jsx("main", { className: cn("flex-1", isChatRoute || isWorkspaceAppHostRoute
|
|
433
1103
|
? "min-h-0 overflow-hidden"
|
|
434
1104
|
: "overflow-y-auto"), children: showHeader ? (_jsx("div", { className: "mx-auto max-w-7xl space-y-10 px-4 py-6 sm:px-6", children: children })) : (children) })] }));
|
|
435
|
-
const content = isChatRoute ? (
|
|
436
|
-
|
|
1105
|
+
const content = isChatRoute ? (_jsxs("div", { className: cn("agent-layout-main-surface flex min-w-0 flex-1 overflow-hidden", chatFirstMode && "dispatch-chat-first-surface"), children: [appContent, chatFirstMode && chatFirstSurfacePanel.open ? (_jsxs(ChatFirstSurfacePanel, { width: chatFirstSurfaceResize.width, onResizePointerDown: chatFirstSurfaceResize.onPointerDown, copy: chatFirstCopy, children: [_jsx(ChatFirstSurfaceTabs, { tabs: chatFirstSurfaceTabs.tabs, activeTabId: chatFirstSurfaceTabs.activeTabId, onActivate: activateChatFirstSurfaceTab, onClose: closeChatFirstSurfaceTab, onCloseOthers: (tab) => {
|
|
1106
|
+
activateChatFirstSurfaceTab(tab);
|
|
1107
|
+
chatFirstSurfaceTabsStore.closeOthers(tab.id);
|
|
1108
|
+
}, onCloseToRight: (tab) => {
|
|
1109
|
+
const targetIndex = chatFirstSurfaceTabs.tabs.findIndex((candidate) => candidate.id === tab.id);
|
|
1110
|
+
const activeIndex = chatFirstSurfaceTabs.tabs.findIndex((candidate) => candidate.id === chatFirstSurfaceTabs.activeTabId);
|
|
1111
|
+
if (activeIndex > targetIndex)
|
|
1112
|
+
activateChatFirstSurfaceTab(tab);
|
|
1113
|
+
chatFirstSurfaceTabsStore.closeToRight(tab.id);
|
|
1114
|
+
}, onCloseAll: closeAllChatFirstSurfaceTabs, onOpenSurface: openChatFirstSurface, copy: chatFirstCopy }), chatFirstSurfaceTabs.tabs.length > 0 ? (_jsx(ChatFirstSurfaceContent, { tabs: chatFirstSurfaceTabs.tabs, activeTabId: chatFirstSurfaceTabs.activeTabId, renderTab: renderChatFirstSurfaceTab })) : null] })) : null] })) : (_jsx(AgentSidebar, { position: "right", defaultOpen: false, agentPageHref: agentPageHref, chatViewTransition: true, storageKey: "dispatch", openOnChatRunning: chatHomeHandoffActive, onFullscreenRequest: openAskAgentFullscreen, emptyStateText: t("dispatch.sidebar.emptyAgentText"), suggestions: sidebarSuggestions, children: appContent }));
|
|
1115
|
+
return (_jsx(DispatchExtensionsContext.Provider, { value: extensions, children: _jsx(HeaderActionsProvider, { children: _jsxs("div", { className: "agent-layout-shell flex h-screen w-full overflow-hidden bg-background", children: [_jsx("aside", { "data-collapsed": sidebarCollapsed ? "true" : "false", className: cn("agent-layout-left-drawer hidden shrink-0 flex-col border-e !border-e-sidebar-border bg-sidebar text-sidebar-foreground transition-[width] duration-200 ease-out lg:flex", sidebarCollapsed ? "w-14" : "w-56"), children: _jsx(NavContent, { extensions: extensions, chatFirstMode: chatFirstMode, chatFirstEmbedded: chatFirstEmbedded, collapsed: sidebarCollapsed, chatFirstAppLayout: chatFirstAppLayout, onChatFirstAppLayoutChange: persistChatFirstAppLayout, chatFirstApps: chatFirstAppItems, chatFirstAppsLoading: chatFirstAppsQuery.isLoading, chatFirstAppsError: chatFirstAppsQuery.isError
|
|
1116
|
+
? chatFirstCopy("appsLoadError")
|
|
1117
|
+
: null, chatFirstActiveAppId: activeChatFirstSurfaceTab?.kind === "app"
|
|
1118
|
+
? activeChatFirstSurfaceTab.appId
|
|
1119
|
+
: undefined, onChatFirstAppOpen: (app) => openChatFirstPane({ appId: app.id }), onChatFirstAppsRetry: () => void chatFirstAppsQuery.refetch(), collapsible: true, onCollapsedChange: setSidebarCollapsed }) }), _jsx(Sheet, { open: mobileOpen, onOpenChange: setMobileOpen, children: _jsxs(SheetContent, { side: "left", className: "w-72 p-0 bg-sidebar text-sidebar-foreground [&>button]:hidden", children: [_jsx(SheetTitle, { className: "sr-only", children: t("dispatch.nav.navigation") }), _jsx(SheetDescription, { className: "sr-only", children: t("dispatch.nav.navigationDescription") }), _jsx("div", { className: "flex h-full w-full flex-col", children: _jsx(NavContent, { extensions: extensions, chatFirstMode: chatFirstMode, chatFirstEmbedded: chatFirstEmbedded, collapsed: false, chatFirstAppLayout: chatFirstAppLayout, onChatFirstAppLayoutChange: persistChatFirstAppLayout, chatFirstApps: chatFirstAppItems, chatFirstAppsLoading: chatFirstAppsQuery.isLoading, chatFirstAppsError: chatFirstAppsQuery.isError
|
|
1120
|
+
? chatFirstCopy("appsLoadError")
|
|
1121
|
+
: null, chatFirstActiveAppId: activeChatFirstSurfaceTab?.kind === "app"
|
|
1122
|
+
? activeChatFirstSurfaceTab.appId
|
|
1123
|
+
: undefined, onChatFirstAppOpen: (app) => openChatFirstPane({ appId: app.id }), onChatFirstAppsRetry: () => void chatFirstAppsQuery.refetch(), onNavigate: () => setMobileOpen(false) }) })] }) }), content] }) }) }));
|
|
437
1124
|
}
|
|
438
1125
|
//# sourceMappingURL=Layout.js.map
|