@agent-native/dispatch 0.12.1 → 0.12.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.
@@ -1 +1 @@
1
- {"version":3,"file":"dispatch-shell.d.ts","sourceRoot":"","sources":["../../src/components/dispatch-shell.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AASvC;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,EAC5B,KAAK,EACL,WAAW,EACX,QAAQ,GACT,EAAE;IACD,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,SAAS,CAAC;CACrB,2CA8BA"}
1
+ {"version":3,"file":"dispatch-shell.d.ts","sourceRoot":"","sources":["../../src/components/dispatch-shell.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAUvC;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,EAC5B,KAAK,EACL,WAAW,EACX,QAAQ,GACT,EAAE;IACD,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,SAAS,CAAC;CACrB,2CA+BA"}
@@ -1,5 +1,6 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
2
  import { Popover, PopoverContent, PopoverTrigger, } from "../components/ui/popover.js";
3
+ import { useT } from "@agent-native/core/client";
3
4
  import { IconInfoCircle } from "@tabler/icons-react";
4
5
  import { useSetPageTitle } from "../components/layout/HeaderActions.js";
5
6
  /**
@@ -9,7 +10,8 @@ import { useSetPageTitle } from "../components/layout/HeaderActions.js";
9
10
  * is provided by `Layout` mounted in `root.tsx`.
10
11
  */
11
12
  export function DispatchShell({ title, description, children, }) {
12
- useSetPageTitle(_jsxs("div", { className: "flex items-center gap-2 min-w-0", children: [_jsx("h1", { className: "text-lg font-semibold tracking-tight truncate text-foreground", children: title }), description ? (_jsxs(Popover, { children: [_jsx(PopoverTrigger, { asChild: true, children: _jsx("button", { type: "button", className: "inline-flex h-6 w-6 items-center justify-center rounded-md text-muted-foreground/70 hover:bg-accent hover:text-foreground cursor-pointer", "aria-label": `About ${title}`, children: _jsx(IconInfoCircle, { className: "h-3.5 w-3.5" }) }) }), _jsx(PopoverContent, { side: "bottom", align: "start", className: "max-w-72 text-xs leading-relaxed", children: description })] })) : null] }));
13
+ const t = useT();
14
+ useSetPageTitle(_jsxs("div", { className: "flex items-center gap-2 min-w-0", children: [_jsx("h1", { className: "text-lg font-semibold tracking-tight truncate text-foreground", children: title }), description ? (_jsxs(Popover, { children: [_jsx(PopoverTrigger, { asChild: true, children: _jsx("button", { type: "button", className: "inline-flex h-6 w-6 items-center justify-center rounded-md text-muted-foreground/70 hover:bg-accent hover:text-foreground cursor-pointer", "aria-label": t("dispatch.sidebar.aboutPage", { title }), children: _jsx(IconInfoCircle, { className: "h-3.5 w-3.5" }) }) }), _jsx(PopoverContent, { side: "bottom", align: "start", className: "max-w-72 text-xs leading-relaxed", children: description })] })) : null] }));
13
15
  return _jsx(_Fragment, { children: children });
14
16
  }
15
17
  //# sourceMappingURL=dispatch-shell.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"dispatch-shell.js","sourceRoot":"","sources":["../../src/components/dispatch-shell.tsx"],"names":[],"mappings":";AACA,OAAO,EACL,OAAO,EACP,cAAc,EACd,cAAc,GACf,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACrD,OAAO,EAAE,eAAe,EAAE,MAAM,mCAAmC,CAAC;AAEpE;;;;;GAKG;AACH,MAAM,UAAU,aAAa,CAAC,EAC5B,KAAK,EACL,WAAW,EACX,QAAQ,GAKT;IACC,eAAe,CACb,eAAK,SAAS,EAAC,iCAAiC,aAC9C,aAAI,SAAS,EAAC,+DAA+D,YAC1E,KAAK,GACH,EACJ,WAAW,CAAC,CAAC,CAAC,CACb,MAAC,OAAO,eACN,KAAC,cAAc,IAAC,OAAO,kBACrB,iBACE,IAAI,EAAC,QAAQ,EACb,SAAS,EAAC,0IAA0I,gBACxI,SAAS,KAAK,EAAE,YAE5B,KAAC,cAAc,IAAC,SAAS,EAAC,aAAa,GAAG,GACnC,GACM,EACjB,KAAC,cAAc,IACb,IAAI,EAAC,QAAQ,EACb,KAAK,EAAC,OAAO,EACb,SAAS,EAAC,kCAAkC,YAE3C,WAAW,GACG,IACT,CACX,CAAC,CAAC,CAAC,IAAI,IACJ,CACP,CAAC;IAEF,OAAO,4BAAG,QAAQ,GAAI,CAAC;AACzB,CAAC","sourcesContent":["import { type ReactNode } from \"react\";\nimport {\n Popover,\n PopoverContent,\n PopoverTrigger,\n} from \"@/components/ui/popover\";\nimport { IconInfoCircle } from \"@tabler/icons-react\";\nimport { useSetPageTitle } from \"@/components/layout/HeaderActions\";\n\n/**\n * DispatchShell renders the per-page title (with an optional click-to-open\n * description popover) into the global header via the HeaderActions store.\n * The actual chrome (sidebar, AgentSidebar, header bar with AgentToggleButton)\n * is provided by `Layout` mounted in `root.tsx`.\n */\nexport function DispatchShell({\n title,\n description,\n children,\n}: {\n title: string;\n description?: string;\n children: ReactNode;\n}) {\n useSetPageTitle(\n <div className=\"flex items-center gap-2 min-w-0\">\n <h1 className=\"text-lg font-semibold tracking-tight truncate text-foreground\">\n {title}\n </h1>\n {description ? (\n <Popover>\n <PopoverTrigger asChild>\n <button\n type=\"button\"\n className=\"inline-flex h-6 w-6 items-center justify-center rounded-md text-muted-foreground/70 hover:bg-accent hover:text-foreground cursor-pointer\"\n aria-label={`About ${title}`}\n >\n <IconInfoCircle className=\"h-3.5 w-3.5\" />\n </button>\n </PopoverTrigger>\n <PopoverContent\n side=\"bottom\"\n align=\"start\"\n className=\"max-w-72 text-xs leading-relaxed\"\n >\n {description}\n </PopoverContent>\n </Popover>\n ) : null}\n </div>,\n );\n\n return <>{children}</>;\n}\n"]}
1
+ {"version":3,"file":"dispatch-shell.js","sourceRoot":"","sources":["../../src/components/dispatch-shell.tsx"],"names":[],"mappings":";AACA,OAAO,EACL,OAAO,EACP,cAAc,EACd,cAAc,GACf,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAAE,IAAI,EAAE,MAAM,2BAA2B,CAAC;AACjD,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACrD,OAAO,EAAE,eAAe,EAAE,MAAM,mCAAmC,CAAC;AAEpE;;;;;GAKG;AACH,MAAM,UAAU,aAAa,CAAC,EAC5B,KAAK,EACL,WAAW,EACX,QAAQ,GAKT;IACC,MAAM,CAAC,GAAG,IAAI,EAAE,CAAC;IACjB,eAAe,CACb,eAAK,SAAS,EAAC,iCAAiC,aAC9C,aAAI,SAAS,EAAC,+DAA+D,YAC1E,KAAK,GACH,EACJ,WAAW,CAAC,CAAC,CAAC,CACb,MAAC,OAAO,eACN,KAAC,cAAc,IAAC,OAAO,kBACrB,iBACE,IAAI,EAAC,QAAQ,EACb,SAAS,EAAC,0IAA0I,gBACxI,CAAC,CAAC,4BAA4B,EAAE,EAAE,KAAK,EAAE,CAAC,YAEtD,KAAC,cAAc,IAAC,SAAS,EAAC,aAAa,GAAG,GACnC,GACM,EACjB,KAAC,cAAc,IACb,IAAI,EAAC,QAAQ,EACb,KAAK,EAAC,OAAO,EACb,SAAS,EAAC,kCAAkC,YAE3C,WAAW,GACG,IACT,CACX,CAAC,CAAC,CAAC,IAAI,IACJ,CACP,CAAC;IAEF,OAAO,4BAAG,QAAQ,GAAI,CAAC;AACzB,CAAC","sourcesContent":["import { type ReactNode } from \"react\";\nimport {\n Popover,\n PopoverContent,\n PopoverTrigger,\n} from \"@/components/ui/popover\";\nimport { useT } from \"@agent-native/core/client\";\nimport { IconInfoCircle } from \"@tabler/icons-react\";\nimport { useSetPageTitle } from \"@/components/layout/HeaderActions\";\n\n/**\n * DispatchShell renders the per-page title (with an optional click-to-open\n * description popover) into the global header via the HeaderActions store.\n * The actual chrome (sidebar, AgentSidebar, header bar with AgentToggleButton)\n * is provided by `Layout` mounted in `root.tsx`.\n */\nexport function DispatchShell({\n title,\n description,\n children,\n}: {\n title: string;\n description?: string;\n children: ReactNode;\n}) {\n const t = useT();\n useSetPageTitle(\n <div className=\"flex items-center gap-2 min-w-0\">\n <h1 className=\"text-lg font-semibold tracking-tight truncate text-foreground\">\n {title}\n </h1>\n {description ? (\n <Popover>\n <PopoverTrigger asChild>\n <button\n type=\"button\"\n className=\"inline-flex h-6 w-6 items-center justify-center rounded-md text-muted-foreground/70 hover:bg-accent hover:text-foreground cursor-pointer\"\n aria-label={t(\"dispatch.sidebar.aboutPage\", { title })}\n >\n <IconInfoCircle className=\"h-3.5 w-3.5\" />\n </button>\n </PopoverTrigger>\n <PopoverContent\n side=\"bottom\"\n align=\"start\"\n className=\"max-w-72 text-xs leading-relaxed\"\n >\n {description}\n </PopoverContent>\n </Popover>\n ) : null}\n </div>,\n );\n\n return <>{children}</>;\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"Layout.d.ts","sourceRoot":"","sources":["../../../src/components/layout/Layout.tsx"],"names":[],"mappings":"AAAA,OAAO,EAKL,KAAK,aAAa,EAElB,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AA8Df,MAAM,MAAM,kBAAkB,GAAG,SAAS,GAAG,YAAY,CAAC;AAE1D,MAAM,MAAM,eAAe,GAAG,aAAa,CAAC;IAC1C,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACvB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC,CAAC;AAEH,MAAM,WAAW,eAAe;IAC9B,uEAAuE;IACvE,EAAE,EAAE,MAAM,CAAC;IACX,iFAAiF;IACjF,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,eAAe,CAAC;IACvB,mFAAmF;IACnF,OAAO,CAAC,EAAE,kBAAkB,CAAC;IAC7B,gEAAgE;IAChE,KAAK,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC;CACvC;AAED,MAAM,WAAW,uBAAuB;IACtC,8DAA8D;IAC9D,QAAQ,CAAC,EAAE,SAAS,eAAe,EAAE,CAAC;IACtC,kFAAkF;IAClF,SAAS,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CAC/B;AAqdD,wBAAgB,UAAU,CAAC,EACzB,UAAU,EACV,UAAU,GACX,EAAE;IACD,UAAU,CAAC,EAAE,MAAM,IAAI,CAAC;IACxB,UAAU,CAAC,EAAE,uBAAuB,CAAC;CACtC,2CA6IA;AAED,wBAAgB,MAAM,CAAC,EACrB,QAAQ,EACR,UAAU,GACX,EAAE;IACD,QAAQ,EAAE,SAAS,CAAC;IACpB,UAAU,CAAC,EAAE,uBAAuB,CAAC;CACtC,2CAiGA"}
1
+ {"version":3,"file":"Layout.d.ts","sourceRoot":"","sources":["../../../src/components/layout/Layout.tsx"],"names":[],"mappings":"AAAA,OAAO,EAKL,KAAK,aAAa,EAElB,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AAgEf,MAAM,MAAM,kBAAkB,GAAG,SAAS,GAAG,YAAY,CAAC;AAE1D,MAAM,MAAM,eAAe,GAAG,aAAa,CAAC;IAC1C,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACvB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC,CAAC;AAEH,MAAM,WAAW,eAAe;IAC9B,uEAAuE;IACvE,EAAE,EAAE,MAAM,CAAC;IACX,iFAAiF;IACjF,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,eAAe,CAAC;IACvB,mFAAmF;IACnF,OAAO,CAAC,EAAE,kBAAkB,CAAC;IAC7B,gEAAgE;IAChE,KAAK,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC;CACvC;AAED,MAAM,WAAW,uBAAuB;IACtC,8DAA8D;IAC9D,QAAQ,CAAC,EAAE,SAAS,eAAe,EAAE,CAAC;IACtC,kFAAkF;IAClF,SAAS,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CAC/B;AAieD,wBAAgB,UAAU,CAAC,EACzB,UAAU,EACV,UAAU,GACX,EAAE;IACD,UAAU,CAAC,EAAE,MAAM,IAAI,CAAC;IACxB,UAAU,CAAC,EAAE,uBAAuB,CAAC;CACtC,2CA0JA;AAED,wBAAgB,MAAM,CAAC,EACrB,QAAQ,EACR,UAAU,GACX,EAAE;IACD,QAAQ,EAAE,SAAS,CAAC;IACpB,UAAU,CAAC,EAAE,uBAAuB,CAAC;CACtC,2CAyGA"}
@@ -1,7 +1,7 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
2
  import { useEffect, useMemo, useRef, useState, } from "react";
3
3
  import { NavLink, useLocation, useNavigate } from "react-router";
4
- import { AgentSidebar, FeedbackButton, appBasePath, appPath, focusAgentChat, navigateWithAgentChatViewTransition, useActionQuery, useAgentChatHomeHandoff, useAgentChatHomeHandoffLinks, useChatThreads, } from "@agent-native/core/client";
4
+ import { AgentSidebar, FeedbackButton, appBasePath, appPath, focusAgentChat, navigateWithAgentChatViewTransition, useActionQuery, useAgentChatHomeHandoff, useAgentChatHomeHandoffLinks, useChatThreads, useFormatters, useT, } from "@agent-native/core/client";
5
5
  import { ExtensionsSidebarSection } from "@agent-native/core/client/extensions";
6
6
  import { InvitationBanner, OrgSwitcher } from "@agent-native/core/client/org";
7
7
  import { IconArrowUpRight, IconApps, IconBrain, IconChartBar, IconBrandTelegram, IconKey, IconChevronDown, IconDots, IconEdit, IconLayersSubtract, IconMessageQuestion, IconMessages, IconPlus, IconPlugConnected, IconBroadcast, IconFingerprint, IconHistory, IconPuzzle, IconSettings, IconShieldCheck, IconUsersGroup, } from "@tabler/icons-react";
@@ -136,11 +136,6 @@ const OPERATIONS_NAV_ITEMS = [
136
136
  },
137
137
  ];
138
138
  const EMPTY_NAV_ITEMS = [];
139
- const SIDEBAR_SUGGESTIONS = [
140
- "Build a workspace app for X",
141
- "Route Slack mentions to my analytics app",
142
- "Grant my OpenAI key to this app",
143
- ];
144
139
  const CHROMELESS_PATHS = ["/approval"];
145
140
  // Routes whose page renders its own toolbar (with NotificationsBell + AgentToggleButton).
146
141
  // Layout still mounts the sidebar + AgentSidebar, but skips its own Header so
@@ -212,7 +207,7 @@ function threadIdFromPath(pathname) {
212
207
  return null;
213
208
  }
214
209
  }
215
- function formatThreadAge(updatedAt) {
210
+ function formatThreadAge(updatedAt, formatDate) {
216
211
  const diffMs = Math.max(0, Date.now() - updatedAt);
217
212
  const minutes = Math.floor(diffMs / 60_000);
218
213
  if (minutes < 1)
@@ -225,13 +220,13 @@ function formatThreadAge(updatedAt) {
225
220
  const days = Math.floor(hours / 24);
226
221
  if (days < 7)
227
222
  return `${days}d`;
228
- return new Date(updatedAt).toLocaleDateString([], {
223
+ return formatDate(updatedAt, {
229
224
  month: "short",
230
225
  day: "numeric",
231
226
  });
232
227
  }
233
- function threadTitle(thread) {
234
- return thread.title || thread.preview || "New chat";
228
+ function threadTitle(thread, fallback) {
229
+ return thread.title || thread.preview || fallback;
235
230
  }
236
231
  function threadUpdatedAt(thread) {
237
232
  return Number.isFinite(thread.updatedAt)
@@ -241,6 +236,8 @@ function threadUpdatedAt(thread) {
241
236
  : 0;
242
237
  }
243
238
  function DispatchChatsSection({ onNavigate }) {
239
+ const t = useT();
240
+ const { formatDate } = useFormatters();
244
241
  const navigate = useNavigate();
245
242
  const location = useLocation();
246
243
  const { threads, activeThreadId, createThread, switchThread, renameThread, refreshThreads, } = useChatThreads(undefined, "dispatch", undefined, { autoCreate: false });
@@ -293,7 +290,7 @@ function DispatchChatsSection({ onNavigate }) {
293
290
  }
294
291
  function startRenameThread(thread) {
295
292
  committingRenameRef.current = false;
296
- setRenameDraft(threadTitle(thread));
293
+ setRenameDraft(threadTitle(thread, t("dispatch.sidebar.newChat")));
297
294
  setRenamingThreadId(thread.id);
298
295
  }
299
296
  function cancelRenameThread() {
@@ -319,7 +316,7 @@ function DispatchChatsSection({ onNavigate }) {
319
316
  event.preventDefault();
320
317
  void commitRenameThread();
321
318
  }
322
- return (_jsxs("div", { className: "mt-2 border-s border-sidebar-border/70 ps-3", children: [_jsxs("div", { className: "mb-1 flex h-7 items-center gap-2 pe-1", children: [_jsx("div", { className: "min-w-0 flex-1 text-xs font-medium text-sidebar-foreground/70", children: "Chats" }), _jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsx("button", { type: "button", onClick: handleNewChat, className: "flex size-6 shrink-0 cursor-pointer items-center justify-center rounded-md text-sidebar-foreground/65 transition-colors hover:bg-sidebar-accent hover:text-sidebar-accent-foreground", "aria-label": "New Dispatch chat", children: _jsx(IconPlus, { className: "size-3.5" }) }) }), _jsx(TooltipContent, { children: "New chat" })] })] }), _jsx("div", { className: "grid gap-0.5", children: visibleThreads.length > 0 ? (visibleThreads.map((thread) => {
319
+ return (_jsxs("div", { className: "mt-2 border-s border-sidebar-border/70 ps-3", children: [_jsxs("div", { className: "mb-1 flex h-7 items-center gap-2 pe-1", children: [_jsx("div", { className: "min-w-0 flex-1 text-xs font-medium text-sidebar-foreground/70", children: t("dispatch.sidebar.chats") }), _jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsx("button", { type: "button", onClick: handleNewChat, className: "flex size-6 shrink-0 cursor-pointer items-center justify-center rounded-md text-sidebar-foreground/65 transition-colors hover:bg-sidebar-accent hover:text-sidebar-accent-foreground", "aria-label": t("dispatch.sidebar.newDispatchChat"), children: _jsx(IconPlus, { className: "size-3.5" }) }) }), _jsx(TooltipContent, { children: t("dispatch.sidebar.newChat") })] })] }), _jsx("div", { className: "grid gap-0.5", children: visibleThreads.length > 0 ? (visibleThreads.map((thread) => {
323
320
  const localPathname = localDispatchPath(location.pathname);
324
321
  const isActive = thread.id ===
325
322
  (threadIdFromPath(localPathname) ??
@@ -332,12 +329,17 @@ function DispatchChatsSection({ onNavigate }) {
332
329
  event.preventDefault();
333
330
  cancelRenameThread();
334
331
  }
335
- }, maxLength: 160, "aria-label": `Rename ${threadTitle(thread)}`, className: "h-6 min-w-0 rounded-sm border-sidebar-border bg-background px-1.5 text-xs" }) })) : (_jsxs(_Fragment, { children: [_jsx("button", { type: "button", onClick: () => openThread(thread.id), className: "flex h-full min-w-0 flex-1 cursor-pointer items-center px-2 text-start outline-none focus-visible:ring-2 focus-visible:ring-ring", children: _jsx("span", { className: "min-w-0 flex-1 truncate", children: threadTitle(thread) }) }), _jsxs("div", { className: "relative flex size-7 shrink-0 items-center justify-end pe-1", children: [_jsx("span", { className: "text-[11px] text-sidebar-foreground/50 transition-opacity group-hover:opacity-0 group-focus-within:opacity-0", children: isActive
332
+ }, maxLength: 160, "aria-label": t("dispatch.sidebar.renameThread", {
333
+ title: threadTitle(thread, t("dispatch.sidebar.newChat")),
334
+ }), className: "h-6 min-w-0 rounded-sm border-sidebar-border bg-background px-1.5 text-xs" }) })) : (_jsxs(_Fragment, { children: [_jsx("button", { type: "button", onClick: () => openThread(thread.id), className: "flex h-full min-w-0 flex-1 cursor-pointer items-center px-2 text-start outline-none focus-visible:ring-2 focus-visible:ring-ring", children: _jsx("span", { className: "min-w-0 flex-1 truncate", children: threadTitle(thread, t("dispatch.sidebar.newChat")) }) }), _jsxs("div", { className: "relative flex size-7 shrink-0 items-center justify-end pe-1", children: [_jsx("span", { className: "text-[11px] text-sidebar-foreground/50 transition-opacity group-hover:opacity-0 group-focus-within:opacity-0", children: isActive
336
335
  ? ""
337
- : formatThreadAge(threadUpdatedAt(thread)) }), _jsxs(DropdownMenu, { children: [_jsx(DropdownMenuTrigger, { asChild: true, children: _jsx("button", { type: "button", "aria-label": `Chat options for ${threadTitle(thread)}`, className: "absolute end-1 flex size-6 cursor-pointer items-center justify-center rounded-md text-sidebar-foreground/65 opacity-0 transition-opacity hover:bg-sidebar-accent hover:text-sidebar-accent-foreground focus-visible:opacity-100 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring group-hover:opacity-100 group-focus-within:opacity-100 data-[state=open]:opacity-100", children: _jsx(IconDots, { className: "size-4" }) }) }), _jsx(DropdownMenuContent, { align: "end", side: "right", sideOffset: 6, children: _jsxs(DropdownMenuItem, { onSelect: () => startRenameThread(thread), children: [_jsx(IconEdit, { className: "size-4" }), "Rename chat"] }) })] })] })] })) }, thread.id));
338
- })) : (_jsx("button", { type: "button", onClick: handleNewChat, className: "flex h-8 cursor-pointer items-center rounded-md px-2 text-start text-sm text-sidebar-foreground/70 transition-colors hover:bg-sidebar-accent/65 hover:text-sidebar-accent-foreground", children: _jsx("span", { className: "truncate", children: "New chat" }) })) })] }));
336
+ : formatThreadAge(threadUpdatedAt(thread), formatDate) }), _jsxs(DropdownMenu, { children: [_jsx(DropdownMenuTrigger, { asChild: true, children: _jsx("button", { type: "button", "aria-label": t("dispatch.sidebar.chatOptions", {
337
+ title: threadTitle(thread, t("dispatch.sidebar.newChat")),
338
+ }), className: "absolute end-1 flex size-6 cursor-pointer items-center justify-center rounded-md text-sidebar-foreground/65 opacity-0 transition-opacity hover:bg-sidebar-accent hover:text-sidebar-accent-foreground focus-visible:opacity-100 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring group-hover:opacity-100 group-focus-within:opacity-100 data-[state=open]:opacity-100", children: _jsx(IconDots, { className: "size-4" }) }) }), _jsx(DropdownMenuContent, { align: "end", side: "right", sideOffset: 6, children: _jsxs(DropdownMenuItem, { onSelect: () => startRenameThread(thread), children: [_jsx(IconEdit, { className: "size-4" }), t("dispatch.sidebar.renameChat")] }) })] })] })] })) }, thread.id));
339
+ })) : (_jsx("button", { type: "button", onClick: handleNewChat, className: "flex h-8 cursor-pointer items-center rounded-md px-2 text-start text-sm text-sidebar-foreground/70 transition-colors hover:bg-sidebar-accent/65 hover:text-sidebar-accent-foreground", children: _jsx("span", { className: "truncate", children: t("dispatch.sidebar.newChat") }) })) })] }));
339
340
  }
340
341
  export function NavContent({ onNavigate, extensions, }) {
342
+ const t = useT();
341
343
  const location = useLocation();
342
344
  const navigate = useNavigate();
343
345
  const { data: workspace } = useActionQuery("get-workspace-info", {}, { staleTime: 60_000 });
@@ -354,9 +356,18 @@ export function NavContent({ onNavigate, extensions, }) {
354
356
  ];
355
357
  const localPathname = localDispatchPath(location.pathname);
356
358
  const operationsOpen = operationsNavItems.some((item) => navItemMatchesPath(item, localPathname));
359
+ const navLabel = (item) => {
360
+ const key = item.id === "thread-debug"
361
+ ? "threadDebug"
362
+ : item.id === "workspace"
363
+ ? "resources"
364
+ : item.id;
365
+ return t(`dispatch.nav.${key}`, { defaultValue: item.label });
366
+ };
357
367
  const renderNavItem = (item) => {
358
368
  const Icon = item.icon;
359
369
  const itemMatchesLocalPath = navItemMatchesPath(item, localPathname);
370
+ const label = navLabel(item);
360
371
  return (_jsxs("li", { children: [_jsxs(NavLink, { to: dispatchNavLinkTarget(item.to), onClick: (event) => {
361
372
  if (item.id === "chat" &&
362
373
  localPathname !== "/chat" &&
@@ -375,13 +386,16 @@ export function NavContent({ onNavigate, extensions, }) {
375
386
  return cn("flex h-8 w-full items-center gap-2 rounded-md px-2 text-sm", active
376
387
  ? "bg-sidebar-accent font-medium text-sidebar-accent-foreground"
377
388
  : "text-sidebar-foreground/70 hover:bg-sidebar-accent hover:text-sidebar-accent-foreground");
378
- }, 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: item.label })] }), item.id === "chat" && itemMatchesLocalPath ? (_jsx(DispatchChatsSection, { onNavigate: onNavigate })) : null] }, item.id));
389
+ }, 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 })] }), item.id === "chat" && itemMatchesLocalPath ? (_jsx(DispatchChatsSection, { onNavigate: onNavigate })) : null] }, item.id));
379
390
  };
380
391
  return (_jsxs(_Fragment, { children: [_jsx("div", { className: "border-b px-4 py-3", children: _jsxs("div", { className: "flex items-center gap-3", children: [_jsxs("div", { className: "flex h-9 w-9 items-center justify-center rounded-xl border bg-card text-foreground", children: [_jsx("img", { src: appPath("/agent-native-icon-light.svg"), alt: "", "aria-hidden": "true", className: "block h-4 w-auto shrink-0 dark:hidden" }), _jsx("img", { src: appPath("/agent-native-icon-dark.svg"), alt: "", "aria-hidden": "true", className: "hidden h-4 w-auto shrink-0 dark:block" })] }), _jsxs("div", { className: "min-w-0", children: [_jsx("div", { className: "truncate text-sm font-semibold text-foreground", children: workspaceLabel ?? "Dispatch" }), _jsx("div", { className: "truncate text-xs text-muted-foreground", children: workspaceLabel
381
- ? `Workspace · ${ws?.appCount ?? 0} app${ws?.appCount === 1 ? "" : "s"}`
382
- : "Workspace control plane" })] })] }) }), _jsxs("div", { className: "flex min-h-0 flex-1 flex-col overflow-y-auto", children: [_jsx("nav", { className: "px-2 py-3", children: _jsx("ul", { className: "space-y-0.5", children: primaryNavItems.map(renderNavItem) }) }), _jsxs("div", { className: "mt-auto shrink-0", children: [_jsx("div", { className: "border-t px-2 py-2", children: _jsxs("details", { className: "group", open: operationsOpen, children: [_jsxs("summary", { className: "flex h-8 cursor-pointer list-none items-center justify-between rounded-md px-2 text-xs font-medium uppercase text-sidebar-foreground/50 hover:bg-sidebar-accent hover:text-sidebar-accent-foreground [&::-webkit-details-marker]:hidden", children: [_jsx("span", { children: "Operations" }), _jsx(IconChevronDown, { size: 14, className: "transition-transform group-open:rotate-180" })] }), _jsx("ul", { className: "mt-1 space-y-0.5", children: operationsNavItems.map(renderNavItem) })] }) }), _jsx("div", { className: "border-t px-2 py-1", children: _jsx(ExtensionsSidebarSection, {}) }), _jsx("div", { className: "border-t px-3 py-2", children: _jsx(OrgSwitcher, {}) }), _jsx("div", { className: "border-t px-3 py-2", children: _jsx(FeedbackButton, {}) })] })] })] }));
392
+ ? t("dispatch.sidebar.workspaceSubtitle", {
393
+ count: ws?.appCount ?? 0,
394
+ })
395
+ : t("dispatch.sidebar.workspaceControlPlane") })] })] }) }), _jsxs("div", { className: "flex min-h-0 flex-1 flex-col overflow-y-auto", children: [_jsx("nav", { className: "px-2 py-3", children: _jsx("ul", { className: "space-y-0.5", children: primaryNavItems.map(renderNavItem) }) }), _jsxs("div", { className: "mt-auto shrink-0", children: [_jsx("div", { className: "border-t px-2 py-2", children: _jsxs("details", { className: "group", open: operationsOpen, children: [_jsxs("summary", { className: "flex h-8 cursor-pointer list-none items-center justify-between rounded-md px-2 text-xs font-medium uppercase text-sidebar-foreground/50 hover:bg-sidebar-accent hover:text-sidebar-accent-foreground [&::-webkit-details-marker]:hidden", children: [_jsx("span", { children: t("dispatch.nav.operations") }), _jsx(IconChevronDown, { size: 14, className: "transition-transform group-open:rotate-180" })] }), _jsx("ul", { className: "mt-1 space-y-0.5", children: operationsNavItems.map(renderNavItem) })] }) }), _jsx("div", { className: "border-t px-2 py-1", children: _jsx(ExtensionsSidebarSection, {}) }), _jsx("div", { className: "border-t px-3 py-2", children: _jsx(OrgSwitcher, {}) }), _jsx("div", { className: "border-t px-3 py-2", children: _jsx(FeedbackButton, {}) })] })] })] }));
383
396
  }
384
397
  export function Layout({ children, extensions, }) {
398
+ const t = useT();
385
399
  const location = useLocation();
386
400
  const navigate = useNavigate();
387
401
  const [mobileOpen, setMobileOpen] = useState(false);
@@ -405,8 +419,13 @@ export function Layout({ children, extensions, }) {
405
419
  focusAgentChat();
406
420
  navigateWithAgentChatViewTransition(navigate, dispatchNavLinkTarget("/chat"));
407
421
  }
422
+ const sidebarSuggestions = [
423
+ t("dispatch.sidebar.suggestionBuildApp"),
424
+ t("dispatch.sidebar.suggestionRouteSlack"),
425
+ t("dispatch.sidebar.suggestionGrantKey"),
426
+ ];
408
427
  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 ? "min-h-0 overflow-hidden" : "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) })] }));
409
- const content = isChatRoute ? (appContent) : (_jsx(AgentSidebar, { position: "right", defaultOpen: false, chatViewTransition: true, storageKey: "dispatch", openOnChatRunning: chatHomeHandoffActive, onFullscreenRequest: openAskAgentFullscreen, emptyStateText: "Create apps, manage vault keys, and route work across the workspace.", suggestions: SIDEBAR_SUGGESTIONS, children: appContent }));
410
- return (_jsx(HeaderActionsProvider, { children: _jsxs("div", { className: "flex h-screen w-full overflow-hidden bg-background", children: [_jsx("aside", { className: "hidden lg:flex w-64 shrink-0 flex-col border-e bg-sidebar text-sidebar-foreground", children: _jsx(NavContent, { extensions: extensions }) }), _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: "Navigation" }), _jsx(SheetDescription, { className: "sr-only", children: "Workspace navigation links" }), _jsx("div", { className: "flex h-full w-full flex-col", children: _jsx(NavContent, { extensions: extensions, onNavigate: () => setMobileOpen(false) }) })] }) }), content] }) }));
428
+ const content = isChatRoute ? (appContent) : (_jsx(AgentSidebar, { position: "right", defaultOpen: false, chatViewTransition: true, storageKey: "dispatch", openOnChatRunning: chatHomeHandoffActive, onFullscreenRequest: openAskAgentFullscreen, emptyStateText: t("dispatch.sidebar.emptyAgentText"), suggestions: sidebarSuggestions, children: appContent }));
429
+ return (_jsx(HeaderActionsProvider, { children: _jsxs("div", { className: "flex h-screen w-full overflow-hidden bg-background", children: [_jsx("aside", { className: "hidden lg:flex w-64 shrink-0 flex-col border-e bg-sidebar text-sidebar-foreground", children: _jsx(NavContent, { extensions: extensions }) }), _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, onNavigate: () => setMobileOpen(false) }) })] }) }), content] }) }));
411
430
  }
412
431
  //# sourceMappingURL=Layout.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"Layout.js","sourceRoot":"","sources":["../../../src/components/layout/Layout.tsx"],"names":[],"mappings":";AAAA,OAAO,EACL,SAAS,EACT,OAAO,EACP,MAAM,EACN,QAAQ,GAIT,MAAM,OAAO,CAAC;AACf,OAAO,EAAE,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AACjE,OAAO,EACL,YAAY,EACZ,cAAc,EACd,WAAW,EACX,OAAO,EACP,cAAc,EACd,mCAAmC,EACnC,cAAc,EACd,uBAAuB,EACvB,4BAA4B,EAC5B,cAAc,GAEf,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAAE,wBAAwB,EAAE,MAAM,sCAAsC,CAAC;AAChF,OAAO,EAAE,gBAAgB,EAAE,WAAW,EAAE,MAAM,+BAA+B,CAAC;AAC9E,OAAO,EACL,gBAAgB,EAChB,QAAQ,EACR,SAAS,EACT,YAAY,EACZ,iBAAiB,EACjB,OAAO,EACP,eAAe,EACf,QAAQ,EACR,QAAQ,EACR,kBAAkB,EAClB,mBAAmB,EACnB,YAAY,EACZ,QAAQ,EACR,iBAAiB,EACjB,aAAa,EACb,eAAe,EACf,WAAW,EACX,UAAU,EACV,YAAY,EACZ,eAAe,EACf,cAAc,GACf,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,EAAE,EAAE,MAAM,aAAa,CAAC;AACjC,OAAO,EACL,YAAY,EACZ,mBAAmB,EACnB,gBAAgB,EAChB,mBAAmB,GACpB,MAAM,+BAA+B,CAAC;AACvC,OAAO,EAAE,KAAK,EAAE,MAAM,uBAAuB,CAAC;AAC9C,OAAO,EACL,KAAK,EACL,YAAY,EACZ,gBAAgB,EAChB,UAAU,GACX,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EACL,OAAO,EACP,cAAc,EACd,cAAc,GACf,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAClC,OAAO,EAAE,qBAAqB,EAAE,MAAM,iBAAiB,CAAC;AA6BxD,MAAM,iBAAiB,GAAG;IACxB;QACE,EAAE,EAAE,MAAM;QACV,EAAE,EAAE,OAAO;QACX,KAAK,EAAE,MAAM;QACb,IAAI,EAAE,mBAAmB;QACzB,OAAO,EAAE,SAAS;KACnB;IACD;QACE,EAAE,EAAE,UAAU;QACd,EAAE,EAAE,WAAW;QACf,KAAK,EAAE,UAAU;QACjB,IAAI,EAAE,aAAa;QACnB,OAAO,EAAE,SAAS;KACnB;IACD;QACE,EAAE,EAAE,MAAM;QACV,EAAE,EAAE,OAAO;QACX,KAAK,EAAE,MAAM;QACb,IAAI,EAAE,QAAQ;QACd,OAAO,EAAE,SAAS;KACnB;IACD;QACE,EAAE,EAAE,SAAS;QACb,EAAE,EAAE,UAAU;QACd,KAAK,EAAE,SAAS;QAChB,IAAI,EAAE,YAAY;QAClB,OAAO,EAAE,SAAS;KACnB;IACD;QACE,EAAE,EAAE,OAAO;QACX,EAAE,EAAE,QAAQ;QACZ,KAAK,EAAE,OAAO;QACd,IAAI,EAAE,OAAO;QACb,OAAO,EAAE,SAAS;KACnB;IACD;QACE,EAAE,EAAE,cAAc;QAClB,EAAE,EAAE,eAAe;QACnB,KAAK,EAAE,cAAc;QACrB,IAAI,EAAE,UAAU;QAChB,OAAO,EAAE,SAAS;KACnB;IACD;QACE,EAAE,EAAE,QAAQ;QACZ,EAAE,EAAE,SAAS;QACb,KAAK,EAAE,QAAQ;QACf,IAAI,EAAE,iBAAiB;QACvB,OAAO,EAAE,SAAS;KACnB;CAC4C,CAAC;AAEhD,MAAM,oBAAoB,GAAG;IAC3B;QACE,EAAE,EAAE,WAAW;QACf,EAAE,EAAE,YAAY;QAChB,KAAK,EAAE,WAAW;QAClB,IAAI,EAAE,kBAAkB;QACxB,OAAO,EAAE,YAAY;KACtB;IACD;QACE,EAAE,EAAE,WAAW;QACf,EAAE,EAAE,YAAY;QAChB,KAAK,EAAE,WAAW;QAClB,IAAI,EAAE,iBAAiB;QACvB,OAAO,EAAE,YAAY;KACtB;IACD;QACE,EAAE,EAAE,cAAc;QAClB,EAAE,EAAE,eAAe;QACnB,KAAK,EAAE,cAAc;QACrB,IAAI,EAAE,gBAAgB;QACtB,OAAO,EAAE,YAAY;KACtB;IACD;QACE,EAAE,EAAE,YAAY;QAChB,EAAE,EAAE,aAAa;QACjB,KAAK,EAAE,YAAY;QACnB,IAAI,EAAE,eAAe;QACrB,OAAO,EAAE,YAAY;KACtB;IACD;QACE,EAAE,EAAE,WAAW;QACf,EAAE,EAAE,YAAY;QAChB,KAAK,EAAE,WAAW;QAClB,IAAI,EAAE,eAAe;QACrB,OAAO,EAAE,YAAY;KACtB;IACD;QACE,EAAE,EAAE,OAAO;QACX,EAAE,EAAE,QAAQ;QACZ,KAAK,EAAE,OAAO;QACd,IAAI,EAAE,WAAW;QACjB,OAAO,EAAE,YAAY;KACtB;IACD;QACE,EAAE,EAAE,QAAQ;QACZ,EAAE,EAAE,SAAS;QACb,KAAK,EAAE,QAAQ;QACf,IAAI,EAAE,SAAS;QACf,OAAO,EAAE,YAAY;KACtB;IACD;QACE,EAAE,EAAE,cAAc;QAClB,EAAE,EAAE,eAAe;QACnB,KAAK,EAAE,cAAc;QACrB,IAAI,EAAE,YAAY;QAClB,OAAO,EAAE,YAAY;KACtB;IACD;QACE,EAAE,EAAE,UAAU;QACd,EAAE,EAAE,WAAW;QACf,KAAK,EAAE,UAAU;QACjB,IAAI,EAAE,YAAY;QAClB,OAAO,EAAE,YAAY;KACtB;IACD;QACE,EAAE,EAAE,MAAM;QACV,EAAE,EAAE,OAAO;QACX,KAAK,EAAE,MAAM;QACb,IAAI,EAAE,cAAc;QACpB,OAAO,EAAE,YAAY;KACtB;CAC4C,CAAC;AAEhD,MAAM,eAAe,GAA+B,EAAE,CAAC;AAEvD,MAAM,mBAAmB,GAAG;IAC1B,6BAA6B;IAC7B,0CAA0C;IAC1C,iCAAiC;CAClC,CAAC;AAEF,MAAM,gBAAgB,GAAG,CAAC,WAAW,CAAC,CAAC;AAEvC,0FAA0F;AAC1F,8EAA8E;AAC9E,4BAA4B;AAC5B,SAAS,eAAe,CAAC,QAAgB;IACvC,IAAI,QAAQ,KAAK,QAAQ,IAAI,QAAQ,CAAC,UAAU,CAAC,SAAS,CAAC;QAAE,OAAO,IAAI,CAAC;IACzE,IAAI,QAAQ,KAAK,aAAa,IAAI,QAAQ,CAAC,UAAU,CAAC,cAAc,CAAC;QACnE,OAAO,IAAI,CAAC;IACd,OAAO,KAAK,CAAC;AACf,CAAC;AAQD,SAAS,UAAU,CAAC,IAAqB;IACvC,OAAO,IAAI,CAAC,OAAO,IAAI,YAAY,CAAC;AACtC,CAAC;AAED,SAAS,kBAAkB,CAAC,IAAqB,EAAE,QAAgB;IACjE,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;QACf,IAAI,CAAC;YACH,IAAI,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC;gBAAE,OAAO,IAAI,CAAC;QACxC,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,KAAK,CAAC;QACf,CAAC;IACH,CAAC;IACD,OAAO,QAAQ,KAAK,IAAI,CAAC,EAAE,IAAI,QAAQ,CAAC,UAAU,CAAC,GAAG,IAAI,CAAC,EAAE,GAAG,CAAC,CAAC;AACpE,CAAC;AAED,SAAS,kBAAkB,CACzB,KAAiC,EACjC,OAA2B;IAE3B,OAAO,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,KAAK,OAAO,CAAC,CAAC;AAC9D,CAAC;AAED,SAAS,iBAAiB,CAAC,QAAgB;IACzC,MAAM,QAAQ,GAAG,WAAW,EAAE,CAAC;IAC/B,IAAI,CAAC,QAAQ;QAAE,OAAO,QAAQ,CAAC;IAC/B,IAAI,QAAQ,KAAK,QAAQ;QAAE,OAAO,GAAG,CAAC;IACtC,IAAI,QAAQ,CAAC,UAAU,CAAC,GAAG,QAAQ,GAAG,CAAC,EAAE,CAAC;QACxC,OAAO,QAAQ,CAAC,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,GAAG,CAAC;IAChD,CAAC;IACD,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,SAAS,qBAAqB,CAAC,IAAY;IACzC,IAAI,OAAO,MAAM,KAAK,WAAW;QAAE,OAAO,IAAI,CAAC;IAC/C,MAAM,QAAQ,GAAG,WAAW,EAAE,CAAC;IAC/B,IAAI,CAAC,QAAQ;QAAE,OAAO,IAAI,CAAC;IAC3B,yEAAyE;IACzE,2EAA2E;IAC3E,wEAAwE;IACxE,yEAAyE;IACzE,sEAAsE;IACtE,wDAAwD;IACxD,MAAM,QAAQ,GAAG,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC;IAC1C,MAAM,iBAAiB,GACrB,QAAQ,KAAK,QAAQ,IAAI,QAAQ,CAAC,UAAU,CAAC,GAAG,QAAQ,GAAG,CAAC,CAAC;IAC/D,OAAO,iBAAiB,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;AAClD,CAAC;AAED,SAAS,cAAc,CAAC,QAAgB;IACtC,OAAO,SAAS,kBAAkB,CAAC,QAAQ,CAAC,EAAE,CAAC;AACjD,CAAC;AAED,SAAS,gBAAgB,CAAC,QAAgB;IACxC,MAAM,KAAK,GAAG,QAAQ,CAAC,KAAK,CAAC,kBAAkB,CAAC,CAAC;IACjD,IAAI,CAAC,KAAK;QAAE,OAAO,IAAI,CAAC;IACxB,IAAI,CAAC;QACH,MAAM,KAAK,GAAG,kBAAkB,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;QAClD,OAAO,KAAK,IAAI,IAAI,CAAC;IACvB,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,SAAS,eAAe,CAAC,SAAiB;IACxC,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,CAAC,CAAC;IACnD,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,MAAM,CAAC,CAAC;IAC5C,IAAI,OAAO,GAAG,CAAC;QAAE,OAAO,KAAK,CAAC;IAC9B,IAAI,OAAO,GAAG,EAAE;QAAE,OAAO,GAAG,OAAO,GAAG,CAAC;IACvC,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,GAAG,EAAE,CAAC,CAAC;IACvC,IAAI,KAAK,GAAG,EAAE;QAAE,OAAO,GAAG,KAAK,GAAG,CAAC;IACnC,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,GAAG,EAAE,CAAC,CAAC;IACpC,IAAI,IAAI,GAAG,CAAC;QAAE,OAAO,GAAG,IAAI,GAAG,CAAC;IAChC,OAAO,IAAI,IAAI,CAAC,SAAS,CAAC,CAAC,kBAAkB,CAAC,EAAE,EAAE;QAChD,KAAK,EAAE,OAAO;QACd,GAAG,EAAE,SAAS;KACf,CAAC,CAAC;AACL,CAAC;AAED,SAAS,WAAW,CAAC,MAAyB;IAC5C,OAAO,MAAM,CAAC,KAAK,IAAI,MAAM,CAAC,OAAO,IAAI,UAAU,CAAC;AACtD,CAAC;AAED,SAAS,eAAe,CAAC,MAAyB;IAChD,OAAO,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,SAAS,CAAC;QACtC,CAAC,CAAC,MAAM,CAAC,SAAS;QAClB,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,SAAS,CAAC;YACjC,CAAC,CAAC,MAAM,CAAC,SAAS;YAClB,CAAC,CAAC,CAAC,CAAC;AACV,CAAC;AAED,SAAS,oBAAoB,CAAC,EAAE,UAAU,EAA+B;IACvE,MAAM,QAAQ,GAAG,WAAW,EAAE,CAAC;IAC/B,MAAM,QAAQ,GAAG,WAAW,EAAE,CAAC;IAC/B,MAAM,EACJ,OAAO,EACP,cAAc,EACd,YAAY,EACZ,YAAY,EACZ,YAAY,EACZ,cAAc,GACf,GAAG,cAAc,CAAC,SAAS,EAAE,UAAU,EAAE,SAAS,EAAE,EAAE,UAAU,EAAE,KAAK,EAAE,CAAC,CAAC;IAC5E,MAAM,CAAC,gBAAgB,EAAE,mBAAmB,CAAC,GAAG,QAAQ,CAAgB,IAAI,CAAC,CAAC;IAC9E,MAAM,CAAC,WAAW,EAAE,cAAc,CAAC,GAAG,QAAQ,CAAC,EAAE,CAAC,CAAC;IACnD,MAAM,cAAc,GAAG,MAAM,CAA0B,IAAI,CAAC,CAAC;IAC7D,MAAM,mBAAmB,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;IAE1C,MAAM,cAAc,GAAG,OAAO,CAC5B,GAAG,EAAE,CACH,OAAO;SACJ,MAAM,CACL,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,YAAY,GAAG,CAAC,IAAI,MAAM,CAAC,EAAE,KAAK,cAAc,CACpE;SACA,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,eAAe,CAAC,CAAC,CAAC,GAAG,eAAe,CAAC,CAAC,CAAC,CAAC;SACvD,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,EAChB,CAAC,cAAc,EAAE,OAAO,CAAC,CAC1B,CAAC;IAEF,SAAS,CAAC,GAAG,EAAE;QACb,MAAM,OAAO,GAAG,GAAG,EAAE,CAAC,cAAc,EAAE,CAAC;QACvC,MAAM,aAAa,GAAG,CAAC,KAAY,EAAE,EAAE;YACrC,MAAM,MAAM,GAAI,KAAqB,CAAC,MAEzB,CAAC;YACd,IAAI,MAAM,EAAE,SAAS,KAAK,KAAK;gBAAE,cAAc,EAAE,CAAC;QACpD,CAAC,CAAC;QAEF,MAAM,CAAC,gBAAgB,CAAC,4BAA4B,EAAE,OAAO,CAAC,CAAC;QAC/D,MAAM,CAAC,gBAAgB,CAAC,yBAAyB,EAAE,aAAa,CAAC,CAAC;QAClE,MAAM,CAAC,gBAAgB,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QAC1C,OAAO,GAAG,EAAE;YACV,MAAM,CAAC,mBAAmB,CAAC,4BAA4B,EAAE,OAAO,CAAC,CAAC;YAClE,MAAM,CAAC,mBAAmB,CAAC,yBAAyB,EAAE,aAAa,CAAC,CAAC;YACrE,MAAM,CAAC,mBAAmB,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QAC/C,CAAC,CAAC;IACJ,CAAC,EAAE,CAAC,cAAc,CAAC,CAAC,CAAC;IAErB,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,CAAC,gBAAgB;YAAE,OAAO;QAC9B,qBAAqB,CAAC,GAAG,EAAE;YACzB,cAAc,CAAC,OAAO,EAAE,KAAK,EAAE,CAAC;YAChC,cAAc,CAAC,OAAO,EAAE,MAAM,EAAE,CAAC;QACnC,CAAC,CAAC,CAAC;IACL,CAAC,EAAE,CAAC,gBAAgB,CAAC,CAAC,CAAC;IAEvB,SAAS,UAAU,CAAC,QAAgB,EAAE,OAA6B;QACjE,YAAY,CAAC,QAAQ,CAAC,CAAC;QACvB,mCAAmC,CACjC,QAAQ,EACR,qBAAqB,CACnB,OAAO,EAAE,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,cAAc,CAAC,QAAQ,CAAC,CACpD,CACF,CAAC;QACF,UAAU,EAAE,EAAE,CAAC;QACf,MAAM,CAAC,qBAAqB,CAAC,GAAG,EAAE;YAChC,MAAM,CAAC,aAAa,CAClB,IAAI,WAAW,CAAC,wBAAwB,EAAE;gBACxC,MAAM,EAAE,EAAE,QAAQ,EAAE,SAAS,EAAE,OAAO,EAAE,KAAK,KAAK,IAAI,EAAE;aACzD,CAAC,CACH,CAAC;QACJ,CAAC,CAAC,CAAC;IACL,CAAC;IAED,KAAK,UAAU,aAAa;QAC1B,MAAM,QAAQ,GAAG,MAAM,YAAY,EAAE,CAAC;QACtC,IAAI,QAAQ;YAAE,UAAU,CAAC,QAAQ,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IACtD,CAAC;IAED,SAAS,iBAAiB,CAAC,MAAyB;QAClD,mBAAmB,CAAC,OAAO,GAAG,KAAK,CAAC;QACpC,cAAc,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC;QACpC,mBAAmB,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;IACjC,CAAC;IAED,SAAS,kBAAkB;QACzB,mBAAmB,CAAC,OAAO,GAAG,IAAI,CAAC;QACnC,mBAAmB,CAAC,IAAI,CAAC,CAAC;QAC1B,cAAc,CAAC,EAAE,CAAC,CAAC;IACrB,CAAC;IAED,KAAK,UAAU,kBAAkB;QAC/B,IAAI,mBAAmB,CAAC,OAAO;YAAE,OAAO;QACxC,MAAM,QAAQ,GAAG,gBAAgB,CAAC;QAClC,MAAM,KAAK,GAAG,WAAW,CAAC,IAAI,EAAE,CAAC;QACjC,IAAI,CAAC,QAAQ;YAAE,OAAO;QACtB,mBAAmB,CAAC,OAAO,GAAG,IAAI,CAAC;QACnC,mBAAmB,CAAC,IAAI,CAAC,CAAC;QAC1B,cAAc,CAAC,EAAE,CAAC,CAAC;QACnB,IAAI,KAAK;YAAE,MAAM,YAAY,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;QAC/C,mBAAmB,CAAC,OAAO,GAAG,KAAK,CAAC;IACtC,CAAC;IAED,SAAS,kBAAkB,CAAC,KAAiC;QAC3D,KAAK,CAAC,cAAc,EAAE,CAAC;QACvB,KAAK,kBAAkB,EAAE,CAAC;IAC5B,CAAC;IAED,OAAO,CACL,eAAK,SAAS,EAAC,6CAA6C,aAC1D,eAAK,SAAS,EAAC,uCAAuC,aACpD,cAAK,SAAS,EAAC,+DAA+D,sBAExE,EACN,MAAC,OAAO,eACN,KAAC,cAAc,IAAC,OAAO,kBACrB,iBACE,IAAI,EAAC,QAAQ,EACb,OAAO,EAAE,aAAa,EACtB,SAAS,EAAC,sLAAsL,gBACrL,mBAAmB,YAE9B,KAAC,QAAQ,IAAC,SAAS,EAAC,UAAU,GAAG,GAC1B,GACM,EACjB,KAAC,cAAc,2BAA0B,IACjC,IACN,EACN,cAAK,SAAS,EAAC,cAAc,YAC1B,cAAc,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,CAC3B,cAAc,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE;oBAC5B,MAAM,aAAa,GAAG,iBAAiB,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;oBAC3D,MAAM,QAAQ,GACZ,MAAM,CAAC,EAAE;wBACT,CAAC,gBAAgB,CAAC,aAAa,CAAC;4BAC9B,CAAC,aAAa,KAAK,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC;oBACzD,MAAM,UAAU,GAAG,MAAM,CAAC,EAAE,KAAK,gBAAgB,CAAC;oBAClD,OAAO,CACL,cAEE,SAAS,EAAE,EAAE,CACX,0EAA0E,EAC1E,QAAQ;4BACN,CAAC,CAAC,kDAAkD;4BACpD,CAAC,CAAC,4FAA4F,CACjG,YAEA,UAAU,CAAC,CAAC,CAAC,CACZ,eACE,QAAQ,EAAE,kBAAkB,EAC5B,SAAS,EAAC,gDAAgD,YAE1D,KAAC,KAAK,IACJ,GAAG,EAAE,cAAc,EACnB,KAAK,EAAE,WAAW,EAClB,QAAQ,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,cAAc,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,EACvD,MAAM,EAAE,GAAG,EAAE,CAAC,KAAK,kBAAkB,EAAE,EACvC,SAAS,EAAE,CAAC,KAAK,EAAE,EAAE;oCACnB,IAAI,KAAK,CAAC,GAAG,KAAK,QAAQ,EAAE,CAAC;wCAC3B,KAAK,CAAC,cAAc,EAAE,CAAC;wCACvB,kBAAkB,EAAE,CAAC;oCACvB,CAAC;gCACH,CAAC,EACD,SAAS,EAAE,GAAG,gBACF,UAAU,WAAW,CAAC,MAAM,CAAC,EAAE,EAC3C,SAAS,EAAC,2EAA2E,GACrF,GACG,CACR,CAAC,CAAC,CAAC,CACF,8BACE,iBACE,IAAI,EAAC,QAAQ,EACb,OAAO,EAAE,GAAG,EAAE,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC,EACpC,SAAS,EAAC,kIAAkI,YAE5I,eAAM,SAAS,EAAC,yBAAyB,YACtC,WAAW,CAAC,MAAM,CAAC,GACf,GACA,EACT,eAAK,SAAS,EAAC,6DAA6D,aAC1E,eAAM,SAAS,EAAC,8GAA8G,YAC3H,QAAQ;gDACP,CAAC,CAAC,EAAE;gDACJ,CAAC,CAAC,eAAe,CAAC,eAAe,CAAC,MAAM,CAAC,CAAC,GACvC,EACP,MAAC,YAAY,eACX,KAAC,mBAAmB,IAAC,OAAO,kBAC1B,iBACE,IAAI,EAAC,QAAQ,gBACD,oBAAoB,WAAW,CAAC,MAAM,CAAC,EAAE,EACrD,SAAS,EAAC,8XAA8X,YAExY,KAAC,QAAQ,IAAC,SAAS,EAAC,QAAQ,GAAG,GACxB,GACW,EACtB,KAAC,mBAAmB,IAClB,KAAK,EAAC,KAAK,EACX,IAAI,EAAC,OAAO,EACZ,UAAU,EAAE,CAAC,YAEb,MAAC,gBAAgB,IACf,QAAQ,EAAE,GAAG,EAAE,CAAC,iBAAiB,CAAC,MAAM,CAAC,aAEzC,KAAC,QAAQ,IAAC,SAAS,EAAC,QAAQ,GAAG,mBAEd,GACC,IACT,IACX,IACL,CACJ,IAvEI,MAAM,CAAC,EAAE,CAwEV,CACP,CAAC;gBACJ,CAAC,CAAC,CACH,CAAC,CAAC,CAAC,CACF,iBACE,IAAI,EAAC,QAAQ,EACb,OAAO,EAAE,aAAa,EACtB,SAAS,EAAC,sLAAsL,YAEhM,eAAM,SAAS,EAAC,UAAU,yBAAgB,GACnC,CACV,GACG,IACF,CACP,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,EACzB,UAAU,EACV,UAAU,GAIX;IACC,MAAM,QAAQ,GAAG,WAAW,EAAE,CAAC;IAC/B,MAAM,QAAQ,GAAG,WAAW,EAAE,CAAC;IAC/B,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,GAAG,cAAc,CACxC,oBAAoB,EACpB,EAAE,EACF,EAAE,SAAS,EAAE,MAAM,EAAE,CACtB,CAAC;IACF,MAAM,EAAE,GAAG,SAAsC,CAAC;IAClD,MAAM,cAAc,GAAG,EAAE,EAAE,WAAW,IAAI,EAAE,EAAE,IAAI,IAAI,IAAI,CAAC;IAC3D,MAAM,iBAAiB,GAAG,UAAU,EAAE,QAAQ,IAAI,eAAe,CAAC;IAClE,MAAM,eAAe,GAAG;QACtB,GAAG,iBAAiB;QACpB,GAAG,kBAAkB,CAAC,iBAAiB,EAAE,SAAS,CAAC;KACpD,CAAC;IACF,MAAM,kBAAkB,GAAG;QACzB,GAAG,oBAAoB;QACvB,GAAG,kBAAkB,CAAC,iBAAiB,EAAE,YAAY,CAAC;KACvD,CAAC;IACF,MAAM,aAAa,GAAG,iBAAiB,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;IAC3D,MAAM,cAAc,GAAG,kBAAkB,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CACtD,kBAAkB,CAAC,IAAI,EAAE,aAAa,CAAC,CACxC,CAAC;IAEF,MAAM,aAAa,GAAG,CAAC,IAAqB,EAAE,EAAE;QAC9C,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC;QACvB,MAAM,oBAAoB,GAAG,kBAAkB,CAAC,IAAI,EAAE,aAAa,CAAC,CAAC;QACrE,OAAO,CACL,yBACE,MAAC,OAAO,IACN,EAAE,EAAE,qBAAqB,CAAC,IAAI,CAAC,EAAE,CAAC,EAClC,OAAO,EAAE,CAAC,KAAK,EAAE,EAAE;wBACjB,IACE,IAAI,CAAC,EAAE,KAAK,MAAM;4BAClB,aAAa,KAAK,OAAO;4BACzB,CAAC,KAAK,CAAC,OAAO;4BACd,CAAC,KAAK,CAAC,OAAO;4BACd,CAAC,KAAK,CAAC,QAAQ;4BACf,CAAC,KAAK,CAAC,MAAM,EACb,CAAC;4BACD,KAAK,CAAC,cAAc,EAAE,CAAC;4BACvB,mCAAmC,CACjC,QAAQ,EACR,qBAAqB,CAAC,OAAO,CAAC,CAC/B,CAAC;4BACF,UAAU,EAAE,EAAE,CAAC;4BACf,OAAO;wBACT,CAAC;wBACD,UAAU,EAAE,EAAE,CAAC;oBACjB,CAAC,EACD,SAAS,EAAE,CAAC,EAAE,QAAQ,EAAE,EAAE,EAAE;wBAC1B,MAAM,MAAM,GAAG,QAAQ,IAAI,oBAAoB,CAAC;wBAChD,OAAO,EAAE,CACP,4DAA4D,EAC5D,MAAM;4BACJ,CAAC,CAAC,8DAA8D;4BAChE,CAAC,CAAC,yFAAyF,CAC9F,CAAC;oBACJ,CAAC,aAEA,IAAI,CAAC,CAAC,CAAC,CACN,KAAC,IAAI,IAAC,IAAI,EAAE,EAAE,EAAE,SAAS,EAAC,UAAU,GAAG,CACxC,CAAC,CAAC,CAAC,CACF,eAAM,SAAS,EAAC,kBAAkB,iBAAa,MAAM,GAAG,CACzD,EACD,eAAM,SAAS,EAAC,UAAU,YAAE,IAAI,CAAC,KAAK,GAAQ,IACtC,EACT,IAAI,CAAC,EAAE,KAAK,MAAM,IAAI,oBAAoB,CAAC,CAAC,CAAC,CAC5C,KAAC,oBAAoB,IAAC,UAAU,EAAE,UAAU,GAAI,CACjD,CAAC,CAAC,CAAC,IAAI,KAzCD,IAAI,CAAC,EAAE,CA0CX,CACN,CAAC;IACJ,CAAC,CAAC;IAEF,OAAO,CACL,8BACE,cAAK,SAAS,EAAC,oBAAoB,YACjC,eAAK,SAAS,EAAC,yBAAyB,aACtC,eAAK,SAAS,EAAC,oFAAoF,aACjG,cACE,GAAG,EAAE,OAAO,CAAC,8BAA8B,CAAC,EAC5C,GAAG,EAAC,EAAE,iBACM,MAAM,EAClB,SAAS,EAAC,uCAAuC,GACjD,EACF,cACE,GAAG,EAAE,OAAO,CAAC,6BAA6B,CAAC,EAC3C,GAAG,EAAC,EAAE,iBACM,MAAM,EAClB,SAAS,EAAC,uCAAuC,GACjD,IACE,EACN,eAAK,SAAS,EAAC,SAAS,aACtB,cAAK,SAAS,EAAC,gDAAgD,YAC5D,cAAc,IAAI,UAAU,GACzB,EACN,cAAK,SAAS,EAAC,wCAAwC,YACpD,cAAc;wCACb,CAAC,CAAC,eAAe,EAAE,EAAE,QAAQ,IAAI,CAAC,OAAO,EAAE,EAAE,QAAQ,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,EAAE;wCACxE,CAAC,CAAC,yBAAyB,GACzB,IACF,IACF,GACF,EAEN,eAAK,SAAS,EAAC,8CAA8C,aAC3D,cAAK,SAAS,EAAC,WAAW,YACxB,aAAI,SAAS,EAAC,aAAa,YAAE,eAAe,CAAC,GAAG,CAAC,aAAa,CAAC,GAAM,GACjE,EAEN,eAAK,SAAS,EAAC,kBAAkB,aAC/B,cAAK,SAAS,EAAC,oBAAoB,YACjC,mBAAS,SAAS,EAAC,OAAO,EAAC,IAAI,EAAE,cAAc,aAC7C,mBAAS,SAAS,EAAC,yOAAyO,aAC1P,wCAAuB,EACvB,KAAC,eAAe,IACd,IAAI,EAAE,EAAE,EACR,SAAS,EAAC,4CAA4C,GACtD,IACM,EACV,aAAI,SAAS,EAAC,kBAAkB,YAC7B,kBAAkB,CAAC,GAAG,CAAC,aAAa,CAAC,GACnC,IACG,GACN,EAEN,cAAK,SAAS,EAAC,oBAAoB,YACjC,KAAC,wBAAwB,KAAG,GACxB,EAEN,cAAK,SAAS,EAAC,oBAAoB,YACjC,KAAC,WAAW,KAAG,GACX,EAEN,cAAK,SAAS,EAAC,oBAAoB,YACjC,KAAC,cAAc,KAAG,GACd,IACF,IACF,IACL,CACJ,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,MAAM,CAAC,EACrB,QAAQ,EACR,UAAU,GAIX;IACC,MAAM,QAAQ,GAAG,WAAW,EAAE,CAAC;IAC/B,MAAM,QAAQ,GAAG,WAAW,EAAE,CAAC;IAC/B,MAAM,CAAC,UAAU,EAAE,aAAa,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IACpD,MAAM,aAAa,GAAG,iBAAiB,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;IAC3D,MAAM,WAAW,GACf,aAAa,KAAK,OAAO,IAAI,aAAa,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC;IAClE,MAAM,qBAAqB,GAAG,uBAAuB,CAAC;QACpD,UAAU,EAAE,UAAU;QACtB,UAAU,EAAE,aAAa;QACzB,OAAO,EAAE,CAAC,WAAW;KACtB,CAAC,CAAC;IACH,MAAM,sBAAsB,GAAG;QAC7B,UAAU,EAAE,UAAU;QACtB,UAAU,EAAE,CAAC,QAAgB,EAAE,EAAE,CAC/B,QAAQ,KAAK,OAAO,IAAI,QAAQ,CAAC,UAAU,CAAC,QAAQ,CAAC;KACxD,CAAC;IACF,4BAA4B,CAAC,sBAAsB,CAAC,CAAC;IAErD,IAAI,gBAAgB,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,aAAa,KAAK,IAAI,CAAC,EAAE,CAAC;QAC5D,OAAO,4BAAG,QAAQ,GAAI,CAAC;IACzB,CAAC;IAED,MAAM,UAAU,GAAG,CAAC,WAAW,IAAI,CAAC,eAAe,CAAC,aAAa,CAAC,CAAC;IACnE,SAAS,sBAAsB;QAC7B,cAAc,EAAE,CAAC;QACjB,mCAAmC,CACjC,QAAQ,EACR,qBAAqB,CAAC,OAAO,CAAC,CAC/B,CAAC;IACJ,CAAC;IACD,MAAM,UAAU,GAAG,CACjB,eAAK,SAAS,EAAC,qDAAqD,aACjE,UAAU,CAAC,CAAC,CAAC,KAAC,MAAM,IAAC,YAAY,EAAE,GAAG,EAAE,CAAC,aAAa,CAAC,IAAI,CAAC,GAAI,CAAC,CAAC,CAAC,IAAI,EACxE,KAAC,gBAAgB,KAAG,EACpB,eACE,SAAS,EAAE,EAAE,CACX,QAAQ,EACR,WAAW,CAAC,CAAC,CAAC,yBAAyB,CAAC,CAAC,CAAC,iBAAiB,CAC5D,YAEA,UAAU,CAAC,CAAC,CAAC,CACZ,cAAK,SAAS,EAAC,gDAAgD,YAC5D,QAAQ,GACL,CACP,CAAC,CAAC,CAAC,CACF,QAAQ,CACT,GACI,IACH,CACP,CAAC;IACF,MAAM,OAAO,GAAG,WAAW,CAAC,CAAC,CAAC,CAC5B,UAAU,CACX,CAAC,CAAC,CAAC,CACF,KAAC,YAAY,IACX,QAAQ,EAAC,OAAO,EAChB,WAAW,EAAE,KAAK,EAClB,kBAAkB,QAClB,UAAU,EAAC,UAAU,EACrB,iBAAiB,EAAE,qBAAqB,EACxC,mBAAmB,EAAE,sBAAsB,EAC3C,cAAc,EAAC,sEAAsE,EACrF,WAAW,EAAE,mBAAmB,YAE/B,UAAU,GACE,CAChB,CAAC;IAEF,OAAO,CACL,KAAC,qBAAqB,cACpB,eAAK,SAAS,EAAC,oDAAoD,aACjE,gBAAO,SAAS,EAAC,mFAAmF,YAClG,KAAC,UAAU,IAAC,UAAU,EAAE,UAAU,GAAI,GAChC,EAER,KAAC,KAAK,IAAC,IAAI,EAAE,UAAU,EAAE,YAAY,EAAE,aAAa,YAClD,MAAC,YAAY,IACX,IAAI,EAAC,MAAM,EACX,SAAS,EAAC,+DAA+D,aAEzE,KAAC,UAAU,IAAC,SAAS,EAAC,SAAS,2BAAwB,EACvD,KAAC,gBAAgB,IAAC,SAAS,EAAC,SAAS,2CAElB,EACnB,cAAK,SAAS,EAAC,6BAA6B,YAC1C,KAAC,UAAU,IACT,UAAU,EAAE,UAAU,EACtB,UAAU,EAAE,GAAG,EAAE,CAAC,aAAa,CAAC,KAAK,CAAC,GACtC,GACE,IACO,GACT,EAEP,OAAO,IACJ,GACgB,CACzB,CAAC;AACJ,CAAC","sourcesContent":["import {\n useEffect,\n useMemo,\n useRef,\n useState,\n type ComponentType,\n type FormEvent,\n type ReactNode,\n} from \"react\";\nimport { NavLink, useLocation, useNavigate } from \"react-router\";\nimport {\n AgentSidebar,\n FeedbackButton,\n appBasePath,\n appPath,\n focusAgentChat,\n navigateWithAgentChatViewTransition,\n useActionQuery,\n useAgentChatHomeHandoff,\n useAgentChatHomeHandoffLinks,\n useChatThreads,\n type ChatThreadSummary,\n} from \"@agent-native/core/client\";\nimport { ExtensionsSidebarSection } from \"@agent-native/core/client/extensions\";\nimport { InvitationBanner, OrgSwitcher } from \"@agent-native/core/client/org\";\nimport {\n IconArrowUpRight,\n IconApps,\n IconBrain,\n IconChartBar,\n IconBrandTelegram,\n IconKey,\n IconChevronDown,\n IconDots,\n IconEdit,\n IconLayersSubtract,\n IconMessageQuestion,\n IconMessages,\n IconPlus,\n IconPlugConnected,\n IconBroadcast,\n IconFingerprint,\n IconHistory,\n IconPuzzle,\n IconSettings,\n IconShieldCheck,\n IconUsersGroup,\n} from \"@tabler/icons-react\";\nimport { cn } from \"@/lib/utils\";\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuTrigger,\n} from \"@/components/ui/dropdown-menu\";\nimport { Input } from \"@/components/ui/input\";\nimport {\n Sheet,\n SheetContent,\n SheetDescription,\n SheetTitle,\n} from \"@/components/ui/sheet\";\nimport {\n Tooltip,\n TooltipContent,\n TooltipTrigger,\n} from \"@/components/ui/tooltip\";\nimport { Header } from \"./Header\";\nimport { HeaderActionsProvider } from \"./HeaderActions\";\n\nexport type DispatchNavSection = \"primary\" | \"operations\";\n\nexport type DispatchNavIcon = ComponentType<{\n size?: number | string;\n className?: string;\n}>;\n\nexport interface DispatchNavItem {\n /** Stable id used for keys and navigation.view. Avoid built-in ids. */\n id: string;\n /** React Router path for the tab, usually backed by an app/routes/*.tsx file. */\n to: string;\n label: string;\n icon?: DispatchNavIcon;\n /** Defaults to \"operations\", which is where local management tools usually fit. */\n section?: DispatchNavSection;\n /** Override active matching for nested or multi-route tools. */\n match?: (pathname: string) => boolean;\n}\n\nexport interface DispatchExtensionConfig {\n /** Extra sidebar tabs supplied by the generated workspace. */\n navItems?: readonly DispatchNavItem[];\n /** Extra React Query keys to invalidate when Dispatch receives DB sync events. */\n queryKeys?: readonly string[];\n}\n\nconst PRIMARY_NAV_ITEMS = [\n {\n id: \"chat\",\n to: \"/chat\",\n label: \"Chat\",\n icon: IconMessageQuestion,\n section: \"primary\",\n },\n {\n id: \"overview\",\n to: \"/overview\",\n label: \"Overview\",\n icon: IconBroadcast,\n section: \"primary\",\n },\n {\n id: \"apps\",\n to: \"/apps\",\n label: \"Apps\",\n icon: IconApps,\n section: \"primary\",\n },\n {\n id: \"metrics\",\n to: \"/metrics\",\n label: \"Metrics\",\n icon: IconChartBar,\n section: \"primary\",\n },\n {\n id: \"vault\",\n to: \"/vault\",\n label: \"Vault\",\n icon: IconKey,\n section: \"primary\",\n },\n {\n id: \"integrations\",\n to: \"/integrations\",\n label: \"Integrations\",\n icon: IconPuzzle,\n section: \"primary\",\n },\n {\n id: \"agents\",\n to: \"/agents\",\n label: \"Agents\",\n icon: IconPlugConnected,\n section: \"primary\",\n },\n] as const satisfies readonly DispatchNavItem[];\n\nconst OPERATIONS_NAV_ITEMS = [\n {\n id: \"workspace\",\n to: \"/workspace\",\n label: \"Resources\",\n icon: IconLayersSubtract,\n section: \"operations\",\n },\n {\n id: \"messaging\",\n to: \"/messaging\",\n label: \"Messaging\",\n icon: IconBrandTelegram,\n section: \"operations\",\n },\n {\n id: \"destinations\",\n to: \"/destinations\",\n label: \"Destinations\",\n icon: IconArrowUpRight,\n section: \"operations\",\n },\n {\n id: \"identities\",\n to: \"/identities\",\n label: \"Identities\",\n icon: IconFingerprint,\n section: \"operations\",\n },\n {\n id: \"approvals\",\n to: \"/approvals\",\n label: \"Approvals\",\n icon: IconShieldCheck,\n section: \"operations\",\n },\n {\n id: \"audit\",\n to: \"/audit\",\n label: \"Audit\",\n icon: IconHistory,\n section: \"operations\",\n },\n {\n id: \"dreams\",\n to: \"/dreams\",\n label: \"Dreams\",\n icon: IconBrain,\n section: \"operations\",\n },\n {\n id: \"thread-debug\",\n to: \"/thread-debug\",\n label: \"Thread Debug\",\n icon: IconMessages,\n section: \"operations\",\n },\n {\n id: \"settings\",\n to: \"/settings\",\n label: \"Settings\",\n icon: IconSettings,\n section: \"operations\",\n },\n {\n id: \"team\",\n to: \"/team\",\n label: \"Team\",\n icon: IconUsersGroup,\n section: \"operations\",\n },\n] as const satisfies readonly DispatchNavItem[];\n\nconst EMPTY_NAV_ITEMS: readonly DispatchNavItem[] = [];\n\nconst SIDEBAR_SUGGESTIONS = [\n \"Build a workspace app for X\",\n \"Route Slack mentions to my analytics app\",\n \"Grant my OpenAI key to this app\",\n];\n\nconst CHROMELESS_PATHS = [\"/approval\"];\n\n// Routes whose page renders its own toolbar (with NotificationsBell + AgentToggleButton).\n// Layout still mounts the sidebar + AgentSidebar, but skips its own Header so\n// there's no double-header.\nfunction pageOwnsToolbar(pathname: string): boolean {\n if (pathname === \"/tools\" || pathname.startsWith(\"/tools/\")) return true;\n if (pathname === \"/extensions\" || pathname.startsWith(\"/extensions/\"))\n return true;\n return false;\n}\n\ninterface WorkspaceInfo {\n name: string | null;\n displayName: string | null;\n appCount: number;\n}\n\nfunction sectionFor(item: DispatchNavItem): DispatchNavSection {\n return item.section ?? \"operations\";\n}\n\nfunction navItemMatchesPath(item: DispatchNavItem, pathname: string): boolean {\n if (item.match) {\n try {\n if (item.match(pathname)) return true;\n } catch {\n return false;\n }\n }\n return pathname === item.to || pathname.startsWith(`${item.to}/`);\n}\n\nfunction navItemsForSection(\n items: readonly DispatchNavItem[],\n section: DispatchNavSection,\n): DispatchNavItem[] {\n return items.filter((item) => sectionFor(item) === section);\n}\n\nfunction localDispatchPath(pathname: string): string {\n const basePath = appBasePath();\n if (!basePath) return pathname;\n if (pathname === basePath) return \"/\";\n if (pathname.startsWith(`${basePath}/`)) {\n return pathname.slice(basePath.length) || \"/\";\n }\n return pathname;\n}\n\nfunction dispatchNavLinkTarget(path: string): string {\n if (typeof window === \"undefined\") return path;\n const basePath = appBasePath();\n if (!basePath) return path;\n // Mirror the basename calculation entry.client.tsx uses to configure the\n // router (basePath iff the current URL is under that mount, \"\" otherwise).\n // Reading the live URL directly avoids races with the previous check on\n // `__reactRouterContext.basename`, which could read undefined before the\n // entry script set it — that race produced /dispatch/dispatch/<route>\n // history entries that 404'd on back-button navigation.\n const pathname = window.location.pathname;\n const routerHasBasename =\n pathname === basePath || pathname.startsWith(`${basePath}/`);\n return routerHasBasename ? path : appPath(path);\n}\n\nfunction chatThreadPath(threadId: string): string {\n return `/chat/${encodeURIComponent(threadId)}`;\n}\n\nfunction threadIdFromPath(pathname: string): string | null {\n const match = pathname.match(/^\\/chat\\/([^/]+)/);\n if (!match) return null;\n try {\n const value = decodeURIComponent(match[1]).trim();\n return value || null;\n } catch {\n return null;\n }\n}\n\nfunction formatThreadAge(updatedAt: number) {\n const diffMs = Math.max(0, Date.now() - updatedAt);\n const minutes = Math.floor(diffMs / 60_000);\n if (minutes < 1) return \"now\";\n if (minutes < 60) return `${minutes}m`;\n const hours = Math.floor(minutes / 60);\n if (hours < 24) return `${hours}h`;\n const days = Math.floor(hours / 24);\n if (days < 7) return `${days}d`;\n return new Date(updatedAt).toLocaleDateString([], {\n month: \"short\",\n day: \"numeric\",\n });\n}\n\nfunction threadTitle(thread: ChatThreadSummary) {\n return thread.title || thread.preview || \"New chat\";\n}\n\nfunction threadUpdatedAt(thread: ChatThreadSummary) {\n return Number.isFinite(thread.updatedAt)\n ? thread.updatedAt\n : Number.isFinite(thread.createdAt)\n ? thread.createdAt\n : 0;\n}\n\nfunction DispatchChatsSection({ onNavigate }: { onNavigate?: () => void }) {\n const navigate = useNavigate();\n const location = useLocation();\n const {\n threads,\n activeThreadId,\n createThread,\n switchThread,\n renameThread,\n refreshThreads,\n } = useChatThreads(undefined, \"dispatch\", undefined, { autoCreate: false });\n const [renamingThreadId, setRenamingThreadId] = useState<string | null>(null);\n const [renameDraft, setRenameDraft] = useState(\"\");\n const renameInputRef = useRef<HTMLInputElement | null>(null);\n const committingRenameRef = useRef(false);\n\n const visibleThreads = useMemo(\n () =>\n threads\n .filter(\n (thread) => thread.messageCount > 0 || thread.id === activeThreadId,\n )\n .sort((a, b) => threadUpdatedAt(b) - threadUpdatedAt(a))\n .slice(0, 8),\n [activeThreadId, threads],\n );\n\n useEffect(() => {\n const refresh = () => refreshThreads();\n const handleRunning = (event: Event) => {\n const detail = (event as CustomEvent).detail as\n | { isRunning?: unknown }\n | undefined;\n if (detail?.isRunning === false) refreshThreads();\n };\n\n window.addEventListener(\"agent-chat:threads-updated\", refresh);\n window.addEventListener(\"agentNative.chatRunning\", handleRunning);\n window.addEventListener(\"focus\", refresh);\n return () => {\n window.removeEventListener(\"agent-chat:threads-updated\", refresh);\n window.removeEventListener(\"agentNative.chatRunning\", handleRunning);\n window.removeEventListener(\"focus\", refresh);\n };\n }, [refreshThreads]);\n\n useEffect(() => {\n if (!renamingThreadId) return;\n requestAnimationFrame(() => {\n renameInputRef.current?.focus();\n renameInputRef.current?.select();\n });\n }, [renamingThreadId]);\n\n function openThread(threadId: string, options?: { isNew?: boolean }) {\n switchThread(threadId);\n navigateWithAgentChatViewTransition(\n navigate,\n dispatchNavLinkTarget(\n options?.isNew ? \"/chat\" : chatThreadPath(threadId),\n ),\n );\n onNavigate?.();\n window.requestAnimationFrame(() => {\n window.dispatchEvent(\n new CustomEvent(\"agent-chat:open-thread\", {\n detail: { threadId, newThread: options?.isNew === true },\n }),\n );\n });\n }\n\n async function handleNewChat() {\n const threadId = await createThread();\n if (threadId) openThread(threadId, { isNew: true });\n }\n\n function startRenameThread(thread: ChatThreadSummary) {\n committingRenameRef.current = false;\n setRenameDraft(threadTitle(thread));\n setRenamingThreadId(thread.id);\n }\n\n function cancelRenameThread() {\n committingRenameRef.current = true;\n setRenamingThreadId(null);\n setRenameDraft(\"\");\n }\n\n async function commitRenameThread() {\n if (committingRenameRef.current) return;\n const threadId = renamingThreadId;\n const title = renameDraft.trim();\n if (!threadId) return;\n committingRenameRef.current = true;\n setRenamingThreadId(null);\n setRenameDraft(\"\");\n if (title) await renameThread(threadId, title);\n committingRenameRef.current = false;\n }\n\n function handleRenameSubmit(event: FormEvent<HTMLFormElement>) {\n event.preventDefault();\n void commitRenameThread();\n }\n\n return (\n <div className=\"mt-2 border-s border-sidebar-border/70 ps-3\">\n <div className=\"mb-1 flex h-7 items-center gap-2 pe-1\">\n <div className=\"min-w-0 flex-1 text-xs font-medium text-sidebar-foreground/70\">\n Chats\n </div>\n <Tooltip>\n <TooltipTrigger asChild>\n <button\n type=\"button\"\n onClick={handleNewChat}\n className=\"flex size-6 shrink-0 cursor-pointer items-center justify-center rounded-md text-sidebar-foreground/65 transition-colors hover:bg-sidebar-accent hover:text-sidebar-accent-foreground\"\n aria-label=\"New Dispatch chat\"\n >\n <IconPlus className=\"size-3.5\" />\n </button>\n </TooltipTrigger>\n <TooltipContent>New chat</TooltipContent>\n </Tooltip>\n </div>\n <div className=\"grid gap-0.5\">\n {visibleThreads.length > 0 ? (\n visibleThreads.map((thread) => {\n const localPathname = localDispatchPath(location.pathname);\n const isActive =\n thread.id ===\n (threadIdFromPath(localPathname) ??\n (localPathname === \"/chat\" ? null : activeThreadId));\n const isRenaming = thread.id === renamingThreadId;\n return (\n <div\n key={thread.id}\n className={cn(\n \"group flex h-8 min-w-0 items-center rounded-md text-sm transition-colors\",\n isActive\n ? \"bg-sidebar-accent text-sidebar-accent-foreground\"\n : \"text-sidebar-foreground/80 hover:bg-sidebar-accent/65 hover:text-sidebar-accent-foreground\",\n )}\n >\n {isRenaming ? (\n <form\n onSubmit={handleRenameSubmit}\n className=\"flex h-full min-w-0 flex-1 items-center px-1.5\"\n >\n <Input\n ref={renameInputRef}\n value={renameDraft}\n onChange={(event) => setRenameDraft(event.target.value)}\n onBlur={() => void commitRenameThread()}\n onKeyDown={(event) => {\n if (event.key === \"Escape\") {\n event.preventDefault();\n cancelRenameThread();\n }\n }}\n maxLength={160}\n aria-label={`Rename ${threadTitle(thread)}`}\n className=\"h-6 min-w-0 rounded-sm border-sidebar-border bg-background px-1.5 text-xs\"\n />\n </form>\n ) : (\n <>\n <button\n type=\"button\"\n onClick={() => openThread(thread.id)}\n className=\"flex h-full min-w-0 flex-1 cursor-pointer items-center px-2 text-start outline-none focus-visible:ring-2 focus-visible:ring-ring\"\n >\n <span className=\"min-w-0 flex-1 truncate\">\n {threadTitle(thread)}\n </span>\n </button>\n <div className=\"relative flex size-7 shrink-0 items-center justify-end pe-1\">\n <span className=\"text-[11px] text-sidebar-foreground/50 transition-opacity group-hover:opacity-0 group-focus-within:opacity-0\">\n {isActive\n ? \"\"\n : formatThreadAge(threadUpdatedAt(thread))}\n </span>\n <DropdownMenu>\n <DropdownMenuTrigger asChild>\n <button\n type=\"button\"\n aria-label={`Chat options for ${threadTitle(thread)}`}\n className=\"absolute end-1 flex size-6 cursor-pointer items-center justify-center rounded-md text-sidebar-foreground/65 opacity-0 transition-opacity hover:bg-sidebar-accent hover:text-sidebar-accent-foreground focus-visible:opacity-100 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring group-hover:opacity-100 group-focus-within:opacity-100 data-[state=open]:opacity-100\"\n >\n <IconDots className=\"size-4\" />\n </button>\n </DropdownMenuTrigger>\n <DropdownMenuContent\n align=\"end\"\n side=\"right\"\n sideOffset={6}\n >\n <DropdownMenuItem\n onSelect={() => startRenameThread(thread)}\n >\n <IconEdit className=\"size-4\" />\n Rename chat\n </DropdownMenuItem>\n </DropdownMenuContent>\n </DropdownMenu>\n </div>\n </>\n )}\n </div>\n );\n })\n ) : (\n <button\n type=\"button\"\n onClick={handleNewChat}\n className=\"flex h-8 cursor-pointer items-center rounded-md px-2 text-start text-sm text-sidebar-foreground/70 transition-colors hover:bg-sidebar-accent/65 hover:text-sidebar-accent-foreground\"\n >\n <span className=\"truncate\">New chat</span>\n </button>\n )}\n </div>\n </div>\n );\n}\n\nexport function NavContent({\n onNavigate,\n extensions,\n}: {\n onNavigate?: () => void;\n extensions?: DispatchExtensionConfig;\n}) {\n const location = useLocation();\n const navigate = useNavigate();\n const { data: workspace } = useActionQuery(\n \"get-workspace-info\",\n {},\n { staleTime: 60_000 },\n );\n const ws = workspace as WorkspaceInfo | undefined;\n const workspaceLabel = ws?.displayName ?? ws?.name ?? null;\n const extensionNavItems = extensions?.navItems ?? EMPTY_NAV_ITEMS;\n const primaryNavItems = [\n ...PRIMARY_NAV_ITEMS,\n ...navItemsForSection(extensionNavItems, \"primary\"),\n ];\n const operationsNavItems = [\n ...OPERATIONS_NAV_ITEMS,\n ...navItemsForSection(extensionNavItems, \"operations\"),\n ];\n const localPathname = localDispatchPath(location.pathname);\n const operationsOpen = operationsNavItems.some((item) =>\n navItemMatchesPath(item, localPathname),\n );\n\n const renderNavItem = (item: DispatchNavItem) => {\n const Icon = item.icon;\n const itemMatchesLocalPath = navItemMatchesPath(item, localPathname);\n return (\n <li key={item.id}>\n <NavLink\n to={dispatchNavLinkTarget(item.to)}\n onClick={(event) => {\n if (\n item.id === \"chat\" &&\n localPathname !== \"/chat\" &&\n !event.metaKey &&\n !event.ctrlKey &&\n !event.shiftKey &&\n !event.altKey\n ) {\n event.preventDefault();\n navigateWithAgentChatViewTransition(\n navigate,\n dispatchNavLinkTarget(\"/chat\"),\n );\n onNavigate?.();\n return;\n }\n onNavigate?.();\n }}\n className={({ isActive }) => {\n const active = isActive || itemMatchesLocalPath;\n return cn(\n \"flex h-8 w-full items-center gap-2 rounded-md px-2 text-sm\",\n active\n ? \"bg-sidebar-accent font-medium text-sidebar-accent-foreground\"\n : \"text-sidebar-foreground/70 hover:bg-sidebar-accent hover:text-sidebar-accent-foreground\",\n );\n }}\n >\n {Icon ? (\n <Icon size={16} className=\"shrink-0\" />\n ) : (\n <span className=\"h-4 w-4 shrink-0\" aria-hidden=\"true\" />\n )}\n <span className=\"truncate\">{item.label}</span>\n </NavLink>\n {item.id === \"chat\" && itemMatchesLocalPath ? (\n <DispatchChatsSection onNavigate={onNavigate} />\n ) : null}\n </li>\n );\n };\n\n return (\n <>\n <div className=\"border-b px-4 py-3\">\n <div className=\"flex items-center gap-3\">\n <div className=\"flex h-9 w-9 items-center justify-center rounded-xl border bg-card text-foreground\">\n <img\n src={appPath(\"/agent-native-icon-light.svg\")}\n alt=\"\"\n aria-hidden=\"true\"\n className=\"block h-4 w-auto shrink-0 dark:hidden\"\n />\n <img\n src={appPath(\"/agent-native-icon-dark.svg\")}\n alt=\"\"\n aria-hidden=\"true\"\n className=\"hidden h-4 w-auto shrink-0 dark:block\"\n />\n </div>\n <div className=\"min-w-0\">\n <div className=\"truncate text-sm font-semibold text-foreground\">\n {workspaceLabel ?? \"Dispatch\"}\n </div>\n <div className=\"truncate text-xs text-muted-foreground\">\n {workspaceLabel\n ? `Workspace · ${ws?.appCount ?? 0} app${ws?.appCount === 1 ? \"\" : \"s\"}`\n : \"Workspace control plane\"}\n </div>\n </div>\n </div>\n </div>\n\n <div className=\"flex min-h-0 flex-1 flex-col overflow-y-auto\">\n <nav className=\"px-2 py-3\">\n <ul className=\"space-y-0.5\">{primaryNavItems.map(renderNavItem)}</ul>\n </nav>\n\n <div className=\"mt-auto shrink-0\">\n <div className=\"border-t px-2 py-2\">\n <details className=\"group\" open={operationsOpen}>\n <summary className=\"flex h-8 cursor-pointer list-none items-center justify-between rounded-md px-2 text-xs font-medium uppercase text-sidebar-foreground/50 hover:bg-sidebar-accent hover:text-sidebar-accent-foreground [&::-webkit-details-marker]:hidden\">\n <span>Operations</span>\n <IconChevronDown\n size={14}\n className=\"transition-transform group-open:rotate-180\"\n />\n </summary>\n <ul className=\"mt-1 space-y-0.5\">\n {operationsNavItems.map(renderNavItem)}\n </ul>\n </details>\n </div>\n\n <div className=\"border-t px-2 py-1\">\n <ExtensionsSidebarSection />\n </div>\n\n <div className=\"border-t px-3 py-2\">\n <OrgSwitcher />\n </div>\n\n <div className=\"border-t px-3 py-2\">\n <FeedbackButton />\n </div>\n </div>\n </div>\n </>\n );\n}\n\nexport function Layout({\n children,\n extensions,\n}: {\n children: ReactNode;\n extensions?: DispatchExtensionConfig;\n}) {\n const location = useLocation();\n const navigate = useNavigate();\n const [mobileOpen, setMobileOpen] = useState(false);\n const localPathname = localDispatchPath(location.pathname);\n const isChatRoute =\n localPathname === \"/chat\" || localPathname.startsWith(\"/chat/\");\n const chatHomeHandoffActive = useAgentChatHomeHandoff({\n storageKey: \"dispatch\",\n activePath: localPathname,\n enabled: !isChatRoute,\n });\n const chatHandoffLinkOptions = {\n storageKey: \"dispatch\",\n isChatPath: (pathname: string) =>\n pathname === \"/chat\" || pathname.startsWith(\"/chat/\"),\n };\n useAgentChatHomeHandoffLinks(chatHandoffLinkOptions);\n\n if (CHROMELESS_PATHS.some((path) => localPathname === path)) {\n return <>{children}</>;\n }\n\n const showHeader = !isChatRoute && !pageOwnsToolbar(localPathname);\n function openAskAgentFullscreen() {\n focusAgentChat();\n navigateWithAgentChatViewTransition(\n navigate,\n dispatchNavLinkTarget(\"/chat\"),\n );\n }\n const appContent = (\n <div className=\"flex h-full min-w-0 flex-1 flex-col overflow-hidden\">\n {showHeader ? <Header onOpenMobile={() => setMobileOpen(true)} /> : null}\n <InvitationBanner />\n <main\n className={cn(\n \"flex-1\",\n isChatRoute ? \"min-h-0 overflow-hidden\" : \"overflow-y-auto\",\n )}\n >\n {showHeader ? (\n <div className=\"mx-auto max-w-7xl space-y-10 px-4 py-6 sm:px-6\">\n {children}\n </div>\n ) : (\n children\n )}\n </main>\n </div>\n );\n const content = isChatRoute ? (\n appContent\n ) : (\n <AgentSidebar\n position=\"right\"\n defaultOpen={false}\n chatViewTransition\n storageKey=\"dispatch\"\n openOnChatRunning={chatHomeHandoffActive}\n onFullscreenRequest={openAskAgentFullscreen}\n emptyStateText=\"Create apps, manage vault keys, and route work across the workspace.\"\n suggestions={SIDEBAR_SUGGESTIONS}\n >\n {appContent}\n </AgentSidebar>\n );\n\n return (\n <HeaderActionsProvider>\n <div className=\"flex h-screen w-full overflow-hidden bg-background\">\n <aside className=\"hidden lg:flex w-64 shrink-0 flex-col border-e bg-sidebar text-sidebar-foreground\">\n <NavContent extensions={extensions} />\n </aside>\n\n <Sheet open={mobileOpen} onOpenChange={setMobileOpen}>\n <SheetContent\n side=\"left\"\n className=\"w-72 p-0 bg-sidebar text-sidebar-foreground [&>button]:hidden\"\n >\n <SheetTitle className=\"sr-only\">Navigation</SheetTitle>\n <SheetDescription className=\"sr-only\">\n Workspace navigation links\n </SheetDescription>\n <div className=\"flex h-full w-full flex-col\">\n <NavContent\n extensions={extensions}\n onNavigate={() => setMobileOpen(false)}\n />\n </div>\n </SheetContent>\n </Sheet>\n\n {content}\n </div>\n </HeaderActionsProvider>\n );\n}\n"]}
1
+ {"version":3,"file":"Layout.js","sourceRoot":"","sources":["../../../src/components/layout/Layout.tsx"],"names":[],"mappings":"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","sourcesContent":["import {\n useEffect,\n useMemo,\n useRef,\n useState,\n type ComponentType,\n type FormEvent,\n type ReactNode,\n} from \"react\";\nimport { NavLink, useLocation, useNavigate } from \"react-router\";\nimport {\n AgentSidebar,\n FeedbackButton,\n appBasePath,\n appPath,\n focusAgentChat,\n navigateWithAgentChatViewTransition,\n useActionQuery,\n useAgentChatHomeHandoff,\n useAgentChatHomeHandoffLinks,\n useChatThreads,\n useFormatters,\n useT,\n type ChatThreadSummary,\n} from \"@agent-native/core/client\";\nimport { ExtensionsSidebarSection } from \"@agent-native/core/client/extensions\";\nimport { InvitationBanner, OrgSwitcher } from \"@agent-native/core/client/org\";\nimport {\n IconArrowUpRight,\n IconApps,\n IconBrain,\n IconChartBar,\n IconBrandTelegram,\n IconKey,\n IconChevronDown,\n IconDots,\n IconEdit,\n IconLayersSubtract,\n IconMessageQuestion,\n IconMessages,\n IconPlus,\n IconPlugConnected,\n IconBroadcast,\n IconFingerprint,\n IconHistory,\n IconPuzzle,\n IconSettings,\n IconShieldCheck,\n IconUsersGroup,\n} from \"@tabler/icons-react\";\nimport { cn } from \"@/lib/utils\";\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuTrigger,\n} from \"@/components/ui/dropdown-menu\";\nimport { Input } from \"@/components/ui/input\";\nimport {\n Sheet,\n SheetContent,\n SheetDescription,\n SheetTitle,\n} from \"@/components/ui/sheet\";\nimport {\n Tooltip,\n TooltipContent,\n TooltipTrigger,\n} from \"@/components/ui/tooltip\";\nimport { Header } from \"./Header\";\nimport { HeaderActionsProvider } from \"./HeaderActions\";\n\nexport type DispatchNavSection = \"primary\" | \"operations\";\n\nexport type DispatchNavIcon = ComponentType<{\n size?: number | string;\n className?: string;\n}>;\n\nexport interface DispatchNavItem {\n /** Stable id used for keys and navigation.view. Avoid built-in ids. */\n id: string;\n /** React Router path for the tab, usually backed by an app/routes/*.tsx file. */\n to: string;\n label: string;\n icon?: DispatchNavIcon;\n /** Defaults to \"operations\", which is where local management tools usually fit. */\n section?: DispatchNavSection;\n /** Override active matching for nested or multi-route tools. */\n match?: (pathname: string) => boolean;\n}\n\nexport interface DispatchExtensionConfig {\n /** Extra sidebar tabs supplied by the generated workspace. */\n navItems?: readonly DispatchNavItem[];\n /** Extra React Query keys to invalidate when Dispatch receives DB sync events. */\n queryKeys?: readonly string[];\n}\n\nconst PRIMARY_NAV_ITEMS = [\n {\n id: \"chat\",\n to: \"/chat\",\n label: \"Chat\",\n icon: IconMessageQuestion,\n section: \"primary\",\n },\n {\n id: \"overview\",\n to: \"/overview\",\n label: \"Overview\",\n icon: IconBroadcast,\n section: \"primary\",\n },\n {\n id: \"apps\",\n to: \"/apps\",\n label: \"Apps\",\n icon: IconApps,\n section: \"primary\",\n },\n {\n id: \"metrics\",\n to: \"/metrics\",\n label: \"Metrics\",\n icon: IconChartBar,\n section: \"primary\",\n },\n {\n id: \"vault\",\n to: \"/vault\",\n label: \"Vault\",\n icon: IconKey,\n section: \"primary\",\n },\n {\n id: \"integrations\",\n to: \"/integrations\",\n label: \"Integrations\",\n icon: IconPuzzle,\n section: \"primary\",\n },\n {\n id: \"agents\",\n to: \"/agents\",\n label: \"Agents\",\n icon: IconPlugConnected,\n section: \"primary\",\n },\n] as const satisfies readonly DispatchNavItem[];\n\nconst OPERATIONS_NAV_ITEMS = [\n {\n id: \"workspace\",\n to: \"/workspace\",\n label: \"Resources\",\n icon: IconLayersSubtract,\n section: \"operations\",\n },\n {\n id: \"messaging\",\n to: \"/messaging\",\n label: \"Messaging\",\n icon: IconBrandTelegram,\n section: \"operations\",\n },\n {\n id: \"destinations\",\n to: \"/destinations\",\n label: \"Destinations\",\n icon: IconArrowUpRight,\n section: \"operations\",\n },\n {\n id: \"identities\",\n to: \"/identities\",\n label: \"Identities\",\n icon: IconFingerprint,\n section: \"operations\",\n },\n {\n id: \"approvals\",\n to: \"/approvals\",\n label: \"Approvals\",\n icon: IconShieldCheck,\n section: \"operations\",\n },\n {\n id: \"audit\",\n to: \"/audit\",\n label: \"Audit\",\n icon: IconHistory,\n section: \"operations\",\n },\n {\n id: \"dreams\",\n to: \"/dreams\",\n label: \"Dreams\",\n icon: IconBrain,\n section: \"operations\",\n },\n {\n id: \"thread-debug\",\n to: \"/thread-debug\",\n label: \"Thread Debug\",\n icon: IconMessages,\n section: \"operations\",\n },\n {\n id: \"settings\",\n to: \"/settings\",\n label: \"Settings\",\n icon: IconSettings,\n section: \"operations\",\n },\n {\n id: \"team\",\n to: \"/team\",\n label: \"Team\",\n icon: IconUsersGroup,\n section: \"operations\",\n },\n] as const satisfies readonly DispatchNavItem[];\n\nconst EMPTY_NAV_ITEMS: readonly DispatchNavItem[] = [];\n\nconst CHROMELESS_PATHS = [\"/approval\"];\n\n// Routes whose page renders its own toolbar (with NotificationsBell + AgentToggleButton).\n// Layout still mounts the sidebar + AgentSidebar, but skips its own Header so\n// there's no double-header.\nfunction pageOwnsToolbar(pathname: string): boolean {\n if (pathname === \"/tools\" || pathname.startsWith(\"/tools/\")) return true;\n if (pathname === \"/extensions\" || pathname.startsWith(\"/extensions/\"))\n return true;\n return false;\n}\n\ninterface WorkspaceInfo {\n name: string | null;\n displayName: string | null;\n appCount: number;\n}\n\nfunction sectionFor(item: DispatchNavItem): DispatchNavSection {\n return item.section ?? \"operations\";\n}\n\nfunction navItemMatchesPath(item: DispatchNavItem, pathname: string): boolean {\n if (item.match) {\n try {\n if (item.match(pathname)) return true;\n } catch {\n return false;\n }\n }\n return pathname === item.to || pathname.startsWith(`${item.to}/`);\n}\n\nfunction navItemsForSection(\n items: readonly DispatchNavItem[],\n section: DispatchNavSection,\n): DispatchNavItem[] {\n return items.filter((item) => sectionFor(item) === section);\n}\n\nfunction localDispatchPath(pathname: string): string {\n const basePath = appBasePath();\n if (!basePath) return pathname;\n if (pathname === basePath) return \"/\";\n if (pathname.startsWith(`${basePath}/`)) {\n return pathname.slice(basePath.length) || \"/\";\n }\n return pathname;\n}\n\nfunction dispatchNavLinkTarget(path: string): string {\n if (typeof window === \"undefined\") return path;\n const basePath = appBasePath();\n if (!basePath) return path;\n // Mirror the basename calculation entry.client.tsx uses to configure the\n // router (basePath iff the current URL is under that mount, \"\" otherwise).\n // Reading the live URL directly avoids races with the previous check on\n // `__reactRouterContext.basename`, which could read undefined before the\n // entry script set it — that race produced /dispatch/dispatch/<route>\n // history entries that 404'd on back-button navigation.\n const pathname = window.location.pathname;\n const routerHasBasename =\n pathname === basePath || pathname.startsWith(`${basePath}/`);\n return routerHasBasename ? path : appPath(path);\n}\n\nfunction chatThreadPath(threadId: string): string {\n return `/chat/${encodeURIComponent(threadId)}`;\n}\n\nfunction threadIdFromPath(pathname: string): string | null {\n const match = pathname.match(/^\\/chat\\/([^/]+)/);\n if (!match) return null;\n try {\n const value = decodeURIComponent(match[1]).trim();\n return value || null;\n } catch {\n return null;\n }\n}\n\nfunction formatThreadAge(\n updatedAt: number,\n formatDate: ReturnType<typeof useFormatters>[\"formatDate\"],\n) {\n const diffMs = Math.max(0, Date.now() - updatedAt);\n const minutes = Math.floor(diffMs / 60_000);\n if (minutes < 1) return \"now\";\n if (minutes < 60) return `${minutes}m`;\n const hours = Math.floor(minutes / 60);\n if (hours < 24) return `${hours}h`;\n const days = Math.floor(hours / 24);\n if (days < 7) return `${days}d`;\n return formatDate(updatedAt, {\n month: \"short\",\n day: \"numeric\",\n });\n}\n\nfunction threadTitle(thread: ChatThreadSummary, fallback: string) {\n return thread.title || thread.preview || fallback;\n}\n\nfunction threadUpdatedAt(thread: ChatThreadSummary) {\n return Number.isFinite(thread.updatedAt)\n ? thread.updatedAt\n : Number.isFinite(thread.createdAt)\n ? thread.createdAt\n : 0;\n}\n\nfunction DispatchChatsSection({ onNavigate }: { onNavigate?: () => void }) {\n const t = useT();\n const { formatDate } = useFormatters();\n const navigate = useNavigate();\n const location = useLocation();\n const {\n threads,\n activeThreadId,\n createThread,\n switchThread,\n renameThread,\n refreshThreads,\n } = useChatThreads(undefined, \"dispatch\", undefined, { autoCreate: false });\n const [renamingThreadId, setRenamingThreadId] = useState<string | null>(null);\n const [renameDraft, setRenameDraft] = useState(\"\");\n const renameInputRef = useRef<HTMLInputElement | null>(null);\n const committingRenameRef = useRef(false);\n\n const visibleThreads = useMemo(\n () =>\n threads\n .filter(\n (thread) => thread.messageCount > 0 || thread.id === activeThreadId,\n )\n .sort((a, b) => threadUpdatedAt(b) - threadUpdatedAt(a))\n .slice(0, 8),\n [activeThreadId, threads],\n );\n\n useEffect(() => {\n const refresh = () => refreshThreads();\n const handleRunning = (event: Event) => {\n const detail = (event as CustomEvent).detail as\n | { isRunning?: unknown }\n | undefined;\n if (detail?.isRunning === false) refreshThreads();\n };\n\n window.addEventListener(\"agent-chat:threads-updated\", refresh);\n window.addEventListener(\"agentNative.chatRunning\", handleRunning);\n window.addEventListener(\"focus\", refresh);\n return () => {\n window.removeEventListener(\"agent-chat:threads-updated\", refresh);\n window.removeEventListener(\"agentNative.chatRunning\", handleRunning);\n window.removeEventListener(\"focus\", refresh);\n };\n }, [refreshThreads]);\n\n useEffect(() => {\n if (!renamingThreadId) return;\n requestAnimationFrame(() => {\n renameInputRef.current?.focus();\n renameInputRef.current?.select();\n });\n }, [renamingThreadId]);\n\n function openThread(threadId: string, options?: { isNew?: boolean }) {\n switchThread(threadId);\n navigateWithAgentChatViewTransition(\n navigate,\n dispatchNavLinkTarget(\n options?.isNew ? \"/chat\" : chatThreadPath(threadId),\n ),\n );\n onNavigate?.();\n window.requestAnimationFrame(() => {\n window.dispatchEvent(\n new CustomEvent(\"agent-chat:open-thread\", {\n detail: { threadId, newThread: options?.isNew === true },\n }),\n );\n });\n }\n\n async function handleNewChat() {\n const threadId = await createThread();\n if (threadId) openThread(threadId, { isNew: true });\n }\n\n function startRenameThread(thread: ChatThreadSummary) {\n committingRenameRef.current = false;\n setRenameDraft(threadTitle(thread, t(\"dispatch.sidebar.newChat\")));\n setRenamingThreadId(thread.id);\n }\n\n function cancelRenameThread() {\n committingRenameRef.current = true;\n setRenamingThreadId(null);\n setRenameDraft(\"\");\n }\n\n async function commitRenameThread() {\n if (committingRenameRef.current) return;\n const threadId = renamingThreadId;\n const title = renameDraft.trim();\n if (!threadId) return;\n committingRenameRef.current = true;\n setRenamingThreadId(null);\n setRenameDraft(\"\");\n if (title) await renameThread(threadId, title);\n committingRenameRef.current = false;\n }\n\n function handleRenameSubmit(event: FormEvent<HTMLFormElement>) {\n event.preventDefault();\n void commitRenameThread();\n }\n\n return (\n <div className=\"mt-2 border-s border-sidebar-border/70 ps-3\">\n <div className=\"mb-1 flex h-7 items-center gap-2 pe-1\">\n <div className=\"min-w-0 flex-1 text-xs font-medium text-sidebar-foreground/70\">\n {t(\"dispatch.sidebar.chats\")}\n </div>\n <Tooltip>\n <TooltipTrigger asChild>\n <button\n type=\"button\"\n onClick={handleNewChat}\n className=\"flex size-6 shrink-0 cursor-pointer items-center justify-center rounded-md text-sidebar-foreground/65 transition-colors hover:bg-sidebar-accent hover:text-sidebar-accent-foreground\"\n aria-label={t(\"dispatch.sidebar.newDispatchChat\")}\n >\n <IconPlus className=\"size-3.5\" />\n </button>\n </TooltipTrigger>\n <TooltipContent>{t(\"dispatch.sidebar.newChat\")}</TooltipContent>\n </Tooltip>\n </div>\n <div className=\"grid gap-0.5\">\n {visibleThreads.length > 0 ? (\n visibleThreads.map((thread) => {\n const localPathname = localDispatchPath(location.pathname);\n const isActive =\n thread.id ===\n (threadIdFromPath(localPathname) ??\n (localPathname === \"/chat\" ? null : activeThreadId));\n const isRenaming = thread.id === renamingThreadId;\n return (\n <div\n key={thread.id}\n className={cn(\n \"group flex h-8 min-w-0 items-center rounded-md text-sm transition-colors\",\n isActive\n ? \"bg-sidebar-accent text-sidebar-accent-foreground\"\n : \"text-sidebar-foreground/80 hover:bg-sidebar-accent/65 hover:text-sidebar-accent-foreground\",\n )}\n >\n {isRenaming ? (\n <form\n onSubmit={handleRenameSubmit}\n className=\"flex h-full min-w-0 flex-1 items-center px-1.5\"\n >\n <Input\n ref={renameInputRef}\n value={renameDraft}\n onChange={(event) => setRenameDraft(event.target.value)}\n onBlur={() => void commitRenameThread()}\n onKeyDown={(event) => {\n if (event.key === \"Escape\") {\n event.preventDefault();\n cancelRenameThread();\n }\n }}\n maxLength={160}\n aria-label={t(\"dispatch.sidebar.renameThread\", {\n title: threadTitle(\n thread,\n t(\"dispatch.sidebar.newChat\"),\n ),\n })}\n className=\"h-6 min-w-0 rounded-sm border-sidebar-border bg-background px-1.5 text-xs\"\n />\n </form>\n ) : (\n <>\n <button\n type=\"button\"\n onClick={() => openThread(thread.id)}\n className=\"flex h-full min-w-0 flex-1 cursor-pointer items-center px-2 text-start outline-none focus-visible:ring-2 focus-visible:ring-ring\"\n >\n <span className=\"min-w-0 flex-1 truncate\">\n {threadTitle(thread, t(\"dispatch.sidebar.newChat\"))}\n </span>\n </button>\n <div className=\"relative flex size-7 shrink-0 items-center justify-end pe-1\">\n <span className=\"text-[11px] text-sidebar-foreground/50 transition-opacity group-hover:opacity-0 group-focus-within:opacity-0\">\n {isActive\n ? \"\"\n : formatThreadAge(\n threadUpdatedAt(thread),\n formatDate,\n )}\n </span>\n <DropdownMenu>\n <DropdownMenuTrigger asChild>\n <button\n type=\"button\"\n aria-label={t(\"dispatch.sidebar.chatOptions\", {\n title: threadTitle(\n thread,\n t(\"dispatch.sidebar.newChat\"),\n ),\n })}\n className=\"absolute end-1 flex size-6 cursor-pointer items-center justify-center rounded-md text-sidebar-foreground/65 opacity-0 transition-opacity hover:bg-sidebar-accent hover:text-sidebar-accent-foreground focus-visible:opacity-100 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring group-hover:opacity-100 group-focus-within:opacity-100 data-[state=open]:opacity-100\"\n >\n <IconDots className=\"size-4\" />\n </button>\n </DropdownMenuTrigger>\n <DropdownMenuContent\n align=\"end\"\n side=\"right\"\n sideOffset={6}\n >\n <DropdownMenuItem\n onSelect={() => startRenameThread(thread)}\n >\n <IconEdit className=\"size-4\" />\n {t(\"dispatch.sidebar.renameChat\")}\n </DropdownMenuItem>\n </DropdownMenuContent>\n </DropdownMenu>\n </div>\n </>\n )}\n </div>\n );\n })\n ) : (\n <button\n type=\"button\"\n onClick={handleNewChat}\n className=\"flex h-8 cursor-pointer items-center rounded-md px-2 text-start text-sm text-sidebar-foreground/70 transition-colors hover:bg-sidebar-accent/65 hover:text-sidebar-accent-foreground\"\n >\n <span className=\"truncate\">{t(\"dispatch.sidebar.newChat\")}</span>\n </button>\n )}\n </div>\n </div>\n );\n}\n\nexport function NavContent({\n onNavigate,\n extensions,\n}: {\n onNavigate?: () => void;\n extensions?: DispatchExtensionConfig;\n}) {\n const t = useT();\n const location = useLocation();\n const navigate = useNavigate();\n const { data: workspace } = useActionQuery(\n \"get-workspace-info\",\n {},\n { staleTime: 60_000 },\n );\n const ws = workspace as WorkspaceInfo | undefined;\n const workspaceLabel = ws?.displayName ?? ws?.name ?? null;\n const extensionNavItems = extensions?.navItems ?? EMPTY_NAV_ITEMS;\n const primaryNavItems = [\n ...PRIMARY_NAV_ITEMS,\n ...navItemsForSection(extensionNavItems, \"primary\"),\n ];\n const operationsNavItems = [\n ...OPERATIONS_NAV_ITEMS,\n ...navItemsForSection(extensionNavItems, \"operations\"),\n ];\n const localPathname = localDispatchPath(location.pathname);\n const operationsOpen = operationsNavItems.some((item) =>\n navItemMatchesPath(item, localPathname),\n );\n const navLabel = (item: DispatchNavItem) => {\n const key =\n item.id === \"thread-debug\"\n ? \"threadDebug\"\n : item.id === \"workspace\"\n ? \"resources\"\n : item.id;\n return t(`dispatch.nav.${key}`, { defaultValue: item.label });\n };\n\n const renderNavItem = (item: DispatchNavItem) => {\n const Icon = item.icon;\n const itemMatchesLocalPath = navItemMatchesPath(item, localPathname);\n const label = navLabel(item);\n return (\n <li key={item.id}>\n <NavLink\n to={dispatchNavLinkTarget(item.to)}\n onClick={(event) => {\n if (\n item.id === \"chat\" &&\n localPathname !== \"/chat\" &&\n !event.metaKey &&\n !event.ctrlKey &&\n !event.shiftKey &&\n !event.altKey\n ) {\n event.preventDefault();\n navigateWithAgentChatViewTransition(\n navigate,\n dispatchNavLinkTarget(\"/chat\"),\n );\n onNavigate?.();\n return;\n }\n onNavigate?.();\n }}\n className={({ isActive }) => {\n const active = isActive || itemMatchesLocalPath;\n return cn(\n \"flex h-8 w-full items-center gap-2 rounded-md px-2 text-sm\",\n active\n ? \"bg-sidebar-accent font-medium text-sidebar-accent-foreground\"\n : \"text-sidebar-foreground/70 hover:bg-sidebar-accent hover:text-sidebar-accent-foreground\",\n );\n }}\n >\n {Icon ? (\n <Icon size={16} className=\"shrink-0\" />\n ) : (\n <span className=\"h-4 w-4 shrink-0\" aria-hidden=\"true\" />\n )}\n <span className=\"truncate\">{label}</span>\n </NavLink>\n {item.id === \"chat\" && itemMatchesLocalPath ? (\n <DispatchChatsSection onNavigate={onNavigate} />\n ) : null}\n </li>\n );\n };\n\n return (\n <>\n <div className=\"border-b px-4 py-3\">\n <div className=\"flex items-center gap-3\">\n <div className=\"flex h-9 w-9 items-center justify-center rounded-xl border bg-card text-foreground\">\n <img\n src={appPath(\"/agent-native-icon-light.svg\")}\n alt=\"\"\n aria-hidden=\"true\"\n className=\"block h-4 w-auto shrink-0 dark:hidden\"\n />\n <img\n src={appPath(\"/agent-native-icon-dark.svg\")}\n alt=\"\"\n aria-hidden=\"true\"\n className=\"hidden h-4 w-auto shrink-0 dark:block\"\n />\n </div>\n <div className=\"min-w-0\">\n <div className=\"truncate text-sm font-semibold text-foreground\">\n {workspaceLabel ?? \"Dispatch\"}\n </div>\n <div className=\"truncate text-xs text-muted-foreground\">\n {workspaceLabel\n ? t(\"dispatch.sidebar.workspaceSubtitle\", {\n count: ws?.appCount ?? 0,\n })\n : t(\"dispatch.sidebar.workspaceControlPlane\")}\n </div>\n </div>\n </div>\n </div>\n\n <div className=\"flex min-h-0 flex-1 flex-col overflow-y-auto\">\n <nav className=\"px-2 py-3\">\n <ul className=\"space-y-0.5\">{primaryNavItems.map(renderNavItem)}</ul>\n </nav>\n\n <div className=\"mt-auto shrink-0\">\n <div className=\"border-t px-2 py-2\">\n <details className=\"group\" open={operationsOpen}>\n <summary className=\"flex h-8 cursor-pointer list-none items-center justify-between rounded-md px-2 text-xs font-medium uppercase text-sidebar-foreground/50 hover:bg-sidebar-accent hover:text-sidebar-accent-foreground [&::-webkit-details-marker]:hidden\">\n <span>{t(\"dispatch.nav.operations\")}</span>\n <IconChevronDown\n size={14}\n className=\"transition-transform group-open:rotate-180\"\n />\n </summary>\n <ul className=\"mt-1 space-y-0.5\">\n {operationsNavItems.map(renderNavItem)}\n </ul>\n </details>\n </div>\n\n <div className=\"border-t px-2 py-1\">\n <ExtensionsSidebarSection />\n </div>\n\n <div className=\"border-t px-3 py-2\">\n <OrgSwitcher />\n </div>\n\n <div className=\"border-t px-3 py-2\">\n <FeedbackButton />\n </div>\n </div>\n </div>\n </>\n );\n}\n\nexport function Layout({\n children,\n extensions,\n}: {\n children: ReactNode;\n extensions?: DispatchExtensionConfig;\n}) {\n const t = useT();\n const location = useLocation();\n const navigate = useNavigate();\n const [mobileOpen, setMobileOpen] = useState(false);\n const localPathname = localDispatchPath(location.pathname);\n const isChatRoute =\n localPathname === \"/chat\" || localPathname.startsWith(\"/chat/\");\n const chatHomeHandoffActive = useAgentChatHomeHandoff({\n storageKey: \"dispatch\",\n activePath: localPathname,\n enabled: !isChatRoute,\n });\n const chatHandoffLinkOptions = {\n storageKey: \"dispatch\",\n isChatPath: (pathname: string) =>\n pathname === \"/chat\" || pathname.startsWith(\"/chat/\"),\n };\n useAgentChatHomeHandoffLinks(chatHandoffLinkOptions);\n\n if (CHROMELESS_PATHS.some((path) => localPathname === path)) {\n return <>{children}</>;\n }\n\n const showHeader = !isChatRoute && !pageOwnsToolbar(localPathname);\n function openAskAgentFullscreen() {\n focusAgentChat();\n navigateWithAgentChatViewTransition(\n navigate,\n dispatchNavLinkTarget(\"/chat\"),\n );\n }\n const sidebarSuggestions = [\n t(\"dispatch.sidebar.suggestionBuildApp\"),\n t(\"dispatch.sidebar.suggestionRouteSlack\"),\n t(\"dispatch.sidebar.suggestionGrantKey\"),\n ];\n const appContent = (\n <div className=\"flex h-full min-w-0 flex-1 flex-col overflow-hidden\">\n {showHeader ? <Header onOpenMobile={() => setMobileOpen(true)} /> : null}\n <InvitationBanner />\n <main\n className={cn(\n \"flex-1\",\n isChatRoute ? \"min-h-0 overflow-hidden\" : \"overflow-y-auto\",\n )}\n >\n {showHeader ? (\n <div className=\"mx-auto max-w-7xl space-y-10 px-4 py-6 sm:px-6\">\n {children}\n </div>\n ) : (\n children\n )}\n </main>\n </div>\n );\n const content = isChatRoute ? (\n appContent\n ) : (\n <AgentSidebar\n position=\"right\"\n defaultOpen={false}\n chatViewTransition\n storageKey=\"dispatch\"\n openOnChatRunning={chatHomeHandoffActive}\n onFullscreenRequest={openAskAgentFullscreen}\n emptyStateText={t(\"dispatch.sidebar.emptyAgentText\")}\n suggestions={sidebarSuggestions}\n >\n {appContent}\n </AgentSidebar>\n );\n\n return (\n <HeaderActionsProvider>\n <div className=\"flex h-screen w-full overflow-hidden bg-background\">\n <aside className=\"hidden lg:flex w-64 shrink-0 flex-col border-e bg-sidebar text-sidebar-foreground\">\n <NavContent extensions={extensions} />\n </aside>\n\n <Sheet open={mobileOpen} onOpenChange={setMobileOpen}>\n <SheetContent\n side=\"left\"\n className=\"w-72 p-0 bg-sidebar text-sidebar-foreground [&>button]:hidden\"\n >\n <SheetTitle className=\"sr-only\">\n {t(\"dispatch.nav.navigation\")}\n </SheetTitle>\n <SheetDescription className=\"sr-only\">\n {t(\"dispatch.nav.navigationDescription\")}\n </SheetDescription>\n <div className=\"flex h-full w-full flex-col\">\n <NavContent\n extensions={extensions}\n onNavigate={() => setMobileOpen(false)}\n />\n </div>\n </SheetContent>\n </Sheet>\n\n {content}\n </div>\n </HeaderActionsProvider>\n );\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agent-native/dispatch",
3
- "version": "0.12.1",
3
+ "version": "0.12.2",
4
4
  "type": "module",
5
5
  "description": "Dispatch — workspace control plane for agent-native apps. Vault, integrations, destinations, scheduled jobs, and cross-app delegation, shipped as a single drop-in package.",
6
6
  "license": "MIT",
@@ -100,7 +100,7 @@
100
100
  "typescript": "^6.0.3",
101
101
  "vite": "8.0.3",
102
102
  "vitest": "^4.1.5",
103
- "@agent-native/core": "0.76.4"
103
+ "@agent-native/core": "0.76.6"
104
104
  },
105
105
  "scripts": {
106
106
  "build": "tsc && tsc-alias --resolve-full-paths",
@@ -4,6 +4,7 @@ import {
4
4
  PopoverContent,
5
5
  PopoverTrigger,
6
6
  } from "@/components/ui/popover";
7
+ import { useT } from "@agent-native/core/client";
7
8
  import { IconInfoCircle } from "@tabler/icons-react";
8
9
  import { useSetPageTitle } from "@/components/layout/HeaderActions";
9
10
 
@@ -22,6 +23,7 @@ export function DispatchShell({
22
23
  description?: string;
23
24
  children: ReactNode;
24
25
  }) {
26
+ const t = useT();
25
27
  useSetPageTitle(
26
28
  <div className="flex items-center gap-2 min-w-0">
27
29
  <h1 className="text-lg font-semibold tracking-tight truncate text-foreground">
@@ -33,7 +35,7 @@ export function DispatchShell({
33
35
  <button
34
36
  type="button"
35
37
  className="inline-flex h-6 w-6 items-center justify-center rounded-md text-muted-foreground/70 hover:bg-accent hover:text-foreground cursor-pointer"
36
- aria-label={`About ${title}`}
38
+ aria-label={t("dispatch.sidebar.aboutPage", { title })}
37
39
  >
38
40
  <IconInfoCircle className="h-3.5 w-3.5" />
39
41
  </button>
@@ -19,6 +19,8 @@ import {
19
19
  useAgentChatHomeHandoff,
20
20
  useAgentChatHomeHandoffLinks,
21
21
  useChatThreads,
22
+ useFormatters,
23
+ useT,
22
24
  type ChatThreadSummary,
23
25
  } from "@agent-native/core/client";
24
26
  import { ExtensionsSidebarSection } from "@agent-native/core/client/extensions";
@@ -222,12 +224,6 @@ const OPERATIONS_NAV_ITEMS = [
222
224
 
223
225
  const EMPTY_NAV_ITEMS: readonly DispatchNavItem[] = [];
224
226
 
225
- const SIDEBAR_SUGGESTIONS = [
226
- "Build a workspace app for X",
227
- "Route Slack mentions to my analytics app",
228
- "Grant my OpenAI key to this app",
229
- ];
230
-
231
227
  const CHROMELESS_PATHS = ["/approval"];
232
228
 
233
229
  // Routes whose page renders its own toolbar (with NotificationsBell + AgentToggleButton).
@@ -309,7 +305,10 @@ function threadIdFromPath(pathname: string): string | null {
309
305
  }
310
306
  }
311
307
 
312
- function formatThreadAge(updatedAt: number) {
308
+ function formatThreadAge(
309
+ updatedAt: number,
310
+ formatDate: ReturnType<typeof useFormatters>["formatDate"],
311
+ ) {
313
312
  const diffMs = Math.max(0, Date.now() - updatedAt);
314
313
  const minutes = Math.floor(diffMs / 60_000);
315
314
  if (minutes < 1) return "now";
@@ -318,14 +317,14 @@ function formatThreadAge(updatedAt: number) {
318
317
  if (hours < 24) return `${hours}h`;
319
318
  const days = Math.floor(hours / 24);
320
319
  if (days < 7) return `${days}d`;
321
- return new Date(updatedAt).toLocaleDateString([], {
320
+ return formatDate(updatedAt, {
322
321
  month: "short",
323
322
  day: "numeric",
324
323
  });
325
324
  }
326
325
 
327
- function threadTitle(thread: ChatThreadSummary) {
328
- return thread.title || thread.preview || "New chat";
326
+ function threadTitle(thread: ChatThreadSummary, fallback: string) {
327
+ return thread.title || thread.preview || fallback;
329
328
  }
330
329
 
331
330
  function threadUpdatedAt(thread: ChatThreadSummary) {
@@ -337,6 +336,8 @@ function threadUpdatedAt(thread: ChatThreadSummary) {
337
336
  }
338
337
 
339
338
  function DispatchChatsSection({ onNavigate }: { onNavigate?: () => void }) {
339
+ const t = useT();
340
+ const { formatDate } = useFormatters();
340
341
  const navigate = useNavigate();
341
342
  const location = useLocation();
342
343
  const {
@@ -415,7 +416,7 @@ function DispatchChatsSection({ onNavigate }: { onNavigate?: () => void }) {
415
416
 
416
417
  function startRenameThread(thread: ChatThreadSummary) {
417
418
  committingRenameRef.current = false;
418
- setRenameDraft(threadTitle(thread));
419
+ setRenameDraft(threadTitle(thread, t("dispatch.sidebar.newChat")));
419
420
  setRenamingThreadId(thread.id);
420
421
  }
421
422
 
@@ -446,7 +447,7 @@ function DispatchChatsSection({ onNavigate }: { onNavigate?: () => void }) {
446
447
  <div className="mt-2 border-s border-sidebar-border/70 ps-3">
447
448
  <div className="mb-1 flex h-7 items-center gap-2 pe-1">
448
449
  <div className="min-w-0 flex-1 text-xs font-medium text-sidebar-foreground/70">
449
- Chats
450
+ {t("dispatch.sidebar.chats")}
450
451
  </div>
451
452
  <Tooltip>
452
453
  <TooltipTrigger asChild>
@@ -454,12 +455,12 @@ function DispatchChatsSection({ onNavigate }: { onNavigate?: () => void }) {
454
455
  type="button"
455
456
  onClick={handleNewChat}
456
457
  className="flex size-6 shrink-0 cursor-pointer items-center justify-center rounded-md text-sidebar-foreground/65 transition-colors hover:bg-sidebar-accent hover:text-sidebar-accent-foreground"
457
- aria-label="New Dispatch chat"
458
+ aria-label={t("dispatch.sidebar.newDispatchChat")}
458
459
  >
459
460
  <IconPlus className="size-3.5" />
460
461
  </button>
461
462
  </TooltipTrigger>
462
- <TooltipContent>New chat</TooltipContent>
463
+ <TooltipContent>{t("dispatch.sidebar.newChat")}</TooltipContent>
463
464
  </Tooltip>
464
465
  </div>
465
466
  <div className="grid gap-0.5">
@@ -498,7 +499,12 @@ function DispatchChatsSection({ onNavigate }: { onNavigate?: () => void }) {
498
499
  }
499
500
  }}
500
501
  maxLength={160}
501
- aria-label={`Rename ${threadTitle(thread)}`}
502
+ aria-label={t("dispatch.sidebar.renameThread", {
503
+ title: threadTitle(
504
+ thread,
505
+ t("dispatch.sidebar.newChat"),
506
+ ),
507
+ })}
502
508
  className="h-6 min-w-0 rounded-sm border-sidebar-border bg-background px-1.5 text-xs"
503
509
  />
504
510
  </form>
@@ -510,20 +516,28 @@ function DispatchChatsSection({ onNavigate }: { onNavigate?: () => void }) {
510
516
  className="flex h-full min-w-0 flex-1 cursor-pointer items-center px-2 text-start outline-none focus-visible:ring-2 focus-visible:ring-ring"
511
517
  >
512
518
  <span className="min-w-0 flex-1 truncate">
513
- {threadTitle(thread)}
519
+ {threadTitle(thread, t("dispatch.sidebar.newChat"))}
514
520
  </span>
515
521
  </button>
516
522
  <div className="relative flex size-7 shrink-0 items-center justify-end pe-1">
517
523
  <span className="text-[11px] text-sidebar-foreground/50 transition-opacity group-hover:opacity-0 group-focus-within:opacity-0">
518
524
  {isActive
519
525
  ? ""
520
- : formatThreadAge(threadUpdatedAt(thread))}
526
+ : formatThreadAge(
527
+ threadUpdatedAt(thread),
528
+ formatDate,
529
+ )}
521
530
  </span>
522
531
  <DropdownMenu>
523
532
  <DropdownMenuTrigger asChild>
524
533
  <button
525
534
  type="button"
526
- aria-label={`Chat options for ${threadTitle(thread)}`}
535
+ aria-label={t("dispatch.sidebar.chatOptions", {
536
+ title: threadTitle(
537
+ thread,
538
+ t("dispatch.sidebar.newChat"),
539
+ ),
540
+ })}
527
541
  className="absolute end-1 flex size-6 cursor-pointer items-center justify-center rounded-md text-sidebar-foreground/65 opacity-0 transition-opacity hover:bg-sidebar-accent hover:text-sidebar-accent-foreground focus-visible:opacity-100 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring group-hover:opacity-100 group-focus-within:opacity-100 data-[state=open]:opacity-100"
528
542
  >
529
543
  <IconDots className="size-4" />
@@ -538,7 +552,7 @@ function DispatchChatsSection({ onNavigate }: { onNavigate?: () => void }) {
538
552
  onSelect={() => startRenameThread(thread)}
539
553
  >
540
554
  <IconEdit className="size-4" />
541
- Rename chat
555
+ {t("dispatch.sidebar.renameChat")}
542
556
  </DropdownMenuItem>
543
557
  </DropdownMenuContent>
544
558
  </DropdownMenu>
@@ -554,7 +568,7 @@ function DispatchChatsSection({ onNavigate }: { onNavigate?: () => void }) {
554
568
  onClick={handleNewChat}
555
569
  className="flex h-8 cursor-pointer items-center rounded-md px-2 text-start text-sm text-sidebar-foreground/70 transition-colors hover:bg-sidebar-accent/65 hover:text-sidebar-accent-foreground"
556
570
  >
557
- <span className="truncate">New chat</span>
571
+ <span className="truncate">{t("dispatch.sidebar.newChat")}</span>
558
572
  </button>
559
573
  )}
560
574
  </div>
@@ -569,6 +583,7 @@ export function NavContent({
569
583
  onNavigate?: () => void;
570
584
  extensions?: DispatchExtensionConfig;
571
585
  }) {
586
+ const t = useT();
572
587
  const location = useLocation();
573
588
  const navigate = useNavigate();
574
589
  const { data: workspace } = useActionQuery(
@@ -591,10 +606,20 @@ export function NavContent({
591
606
  const operationsOpen = operationsNavItems.some((item) =>
592
607
  navItemMatchesPath(item, localPathname),
593
608
  );
609
+ const navLabel = (item: DispatchNavItem) => {
610
+ const key =
611
+ item.id === "thread-debug"
612
+ ? "threadDebug"
613
+ : item.id === "workspace"
614
+ ? "resources"
615
+ : item.id;
616
+ return t(`dispatch.nav.${key}`, { defaultValue: item.label });
617
+ };
594
618
 
595
619
  const renderNavItem = (item: DispatchNavItem) => {
596
620
  const Icon = item.icon;
597
621
  const itemMatchesLocalPath = navItemMatchesPath(item, localPathname);
622
+ const label = navLabel(item);
598
623
  return (
599
624
  <li key={item.id}>
600
625
  <NavLink
@@ -633,7 +658,7 @@ export function NavContent({
633
658
  ) : (
634
659
  <span className="h-4 w-4 shrink-0" aria-hidden="true" />
635
660
  )}
636
- <span className="truncate">{item.label}</span>
661
+ <span className="truncate">{label}</span>
637
662
  </NavLink>
638
663
  {item.id === "chat" && itemMatchesLocalPath ? (
639
664
  <DispatchChatsSection onNavigate={onNavigate} />
@@ -666,8 +691,10 @@ export function NavContent({
666
691
  </div>
667
692
  <div className="truncate text-xs text-muted-foreground">
668
693
  {workspaceLabel
669
- ? `Workspace · ${ws?.appCount ?? 0} app${ws?.appCount === 1 ? "" : "s"}`
670
- : "Workspace control plane"}
694
+ ? t("dispatch.sidebar.workspaceSubtitle", {
695
+ count: ws?.appCount ?? 0,
696
+ })
697
+ : t("dispatch.sidebar.workspaceControlPlane")}
671
698
  </div>
672
699
  </div>
673
700
  </div>
@@ -682,7 +709,7 @@ export function NavContent({
682
709
  <div className="border-t px-2 py-2">
683
710
  <details className="group" open={operationsOpen}>
684
711
  <summary className="flex h-8 cursor-pointer list-none items-center justify-between rounded-md px-2 text-xs font-medium uppercase text-sidebar-foreground/50 hover:bg-sidebar-accent hover:text-sidebar-accent-foreground [&::-webkit-details-marker]:hidden">
685
- <span>Operations</span>
712
+ <span>{t("dispatch.nav.operations")}</span>
686
713
  <IconChevronDown
687
714
  size={14}
688
715
  className="transition-transform group-open:rotate-180"
@@ -718,6 +745,7 @@ export function Layout({
718
745
  children: ReactNode;
719
746
  extensions?: DispatchExtensionConfig;
720
747
  }) {
748
+ const t = useT();
721
749
  const location = useLocation();
722
750
  const navigate = useNavigate();
723
751
  const [mobileOpen, setMobileOpen] = useState(false);
@@ -748,6 +776,11 @@ export function Layout({
748
776
  dispatchNavLinkTarget("/chat"),
749
777
  );
750
778
  }
779
+ const sidebarSuggestions = [
780
+ t("dispatch.sidebar.suggestionBuildApp"),
781
+ t("dispatch.sidebar.suggestionRouteSlack"),
782
+ t("dispatch.sidebar.suggestionGrantKey"),
783
+ ];
751
784
  const appContent = (
752
785
  <div className="flex h-full min-w-0 flex-1 flex-col overflow-hidden">
753
786
  {showHeader ? <Header onOpenMobile={() => setMobileOpen(true)} /> : null}
@@ -778,8 +811,8 @@ export function Layout({
778
811
  storageKey="dispatch"
779
812
  openOnChatRunning={chatHomeHandoffActive}
780
813
  onFullscreenRequest={openAskAgentFullscreen}
781
- emptyStateText="Create apps, manage vault keys, and route work across the workspace."
782
- suggestions={SIDEBAR_SUGGESTIONS}
814
+ emptyStateText={t("dispatch.sidebar.emptyAgentText")}
815
+ suggestions={sidebarSuggestions}
783
816
  >
784
817
  {appContent}
785
818
  </AgentSidebar>
@@ -797,9 +830,11 @@ export function Layout({
797
830
  side="left"
798
831
  className="w-72 p-0 bg-sidebar text-sidebar-foreground [&>button]:hidden"
799
832
  >
800
- <SheetTitle className="sr-only">Navigation</SheetTitle>
833
+ <SheetTitle className="sr-only">
834
+ {t("dispatch.nav.navigation")}
835
+ </SheetTitle>
801
836
  <SheetDescription className="sr-only">
802
- Workspace navigation links
837
+ {t("dispatch.nav.navigationDescription")}
803
838
  </SheetDescription>
804
839
  <div className="flex h-full w-full flex-col">
805
840
  <NavContent