@agent-native/dispatch 0.40.2 → 0.40.4-nightly-20260930124743

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,24 @@
1
1
  # @agent-native/dispatch
2
2
 
3
+ ## 0.40.4-nightly-20260930124743
4
+
5
+ ### Patch Changes
6
+
7
+ - Updated dependencies [ce1245c]
8
+ - Updated dependencies [e90dedc]
9
+ - @agent-native/core@0.198.3-nightly-20260930124743
10
+ - @agent-native/toolkit@0.198.3-nightly-20260930124743
11
+
12
+ ## 0.40.3
13
+
14
+ ### Patch Changes
15
+
16
+ - 181ca1d: Keep the package changelog in Dispatch's route wrapper so generated workspaces can render the shared Settings page during SSR.
17
+ - Release all public npm packages with a patch version bump.
18
+ - Updated dependencies
19
+ - Updated dependencies [63c4c02]
20
+ - @agent-native/toolkit@0.198.2
21
+
3
22
  ## 0.40.2
4
23
 
5
24
  ### Patch Changes
@@ -1078,11 +1097,4 @@
1078
1097
  - Updated dependencies [89f194f]
1079
1098
  - @agent-native/toolkit@0.14.3
1080
1099
 
1081
- ## 0.24.6
1082
-
1083
- ### Patch Changes
1084
-
1085
- - Updated dependencies [2db503b]
1086
- - @agent-native/toolkit@0.14.2
1087
-
1088
1100
  For the full list of releases, see the [changelog archive](./changelog/archive/CHANGELOG.md).
@@ -47,9 +47,9 @@ declare const _default: import("node_modules/@agent-native/core/dist").ActionDef
47
47
  notes?: string | undefined;
48
48
  scope?: "org" | "user" | undefined;
49
49
  }, {
50
- message?: undefined;
51
50
  id?: undefined;
52
51
  deleted?: undefined;
52
+ found?: undefined;
53
53
  providers: {
54
54
  id: string;
55
55
  label: string;
@@ -61,11 +61,10 @@ declare const _default: import("node_modules/@agent-native/core/dist").ActionDef
61
61
  }[];
62
62
  count: number;
63
63
  provider?: undefined;
64
- found?: undefined;
65
64
  registered?: undefined;
66
65
  label?: undefined;
67
- } | {
68
66
  message?: undefined;
67
+ } | {
69
68
  id?: undefined;
70
69
  deleted?: undefined;
71
70
  count?: undefined;
@@ -74,8 +73,8 @@ declare const _default: import("node_modules/@agent-native/core/dist").ActionDef
74
73
  provider: import("node_modules/@agent-native/core/dist/provider-api").CustomProviderConfig;
75
74
  registered?: undefined;
76
75
  label?: undefined;
77
- } | {
78
76
  message?: undefined;
77
+ } | {
79
78
  deleted?: undefined;
80
79
  count?: undefined;
81
80
  providers?: undefined;
@@ -84,22 +83,23 @@ declare const _default: import("node_modules/@agent-native/core/dist").ActionDef
84
83
  id: string;
85
84
  registered?: undefined;
86
85
  label?: undefined;
87
- } | {
88
86
  message?: undefined;
87
+ } | {
88
+ found?: undefined;
89
89
  count?: undefined;
90
90
  providers?: undefined;
91
91
  provider?: undefined;
92
- found?: undefined;
93
92
  deleted: boolean;
94
93
  id: string;
95
94
  registered?: undefined;
96
95
  label?: undefined;
96
+ message?: undefined;
97
97
  } | {
98
98
  deleted?: undefined;
99
+ found?: undefined;
99
100
  count?: undefined;
100
101
  providers?: undefined;
101
102
  provider?: undefined;
102
- found?: undefined;
103
103
  registered: boolean;
104
104
  id: string;
105
105
  label: string;
@@ -0,0 +1,10 @@
1
+ export declare function meta(): {
2
+ title: string;
3
+ }[];
4
+ export interface DispatchSettingsPageProps {
5
+ /** Raw CHANGELOG.md behind What's new. */
6
+ changelog: string;
7
+ }
8
+ /** The template route supplies the app's own changelog. */
9
+ export declare function DispatchSettingsPage({ changelog }: DispatchSettingsPageProps): import("node_modules/@types/react").JSX.Element;
10
+ //# sourceMappingURL=settings-page.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"settings-page.d.ts","sourceRoot":"","sources":["../../../src/routes/pages/settings-page.tsx"],"names":[],"mappings":"AAkDA,wBAAgB,IAAI;;IAEnB;AAED,MAAM,WAAW,yBAAyB;IACxC,0CAA0C;IAC1C,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,2DAA2D;AAC3D,wBAAgB,oBAAoB,CAAC,EAAE,SAAS,EAAE,EAAE,yBAAyB,mDA6L5E"}
@@ -0,0 +1,104 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { CHAT_FIRST_MODE_CHANGED_EVENT, readChatFirstModeState, writeChatFirstMode, } from "@agent-native/core/client/agent-chat";
3
+ import { useFeatureFlag, useFeatureFlagState, } from "@agent-native/core/client/feature-flags";
4
+ import { useT } from "@agent-native/core/client/i18n";
5
+ import { SETTINGS_REDESIGN_FLAG } from "@agent-native/core/feature-flags/registry";
6
+ import { ChangelogSettingsCard } from "@agent-native/toolkit/app/changelog";
7
+ import { OrgMembersPage, TeamPage } from "@agent-native/toolkit/app/org";
8
+ import { AccountSettingsCard, CORE_SETTINGS_PAGES, registerSettingsPages, SettingsGroup, SettingsRow, SettingsTabsPage, useAgentSettingsTabs, } from "@agent-native/toolkit/app/settings";
9
+ import { LanguagePicker } from "@agent-native/toolkit/app/shared";
10
+ import { IconShield } from "@tabler/icons-react";
11
+ import { useMemo, useState } from "react";
12
+ import { Link } from "react-router";
13
+ import { Button } from "../../components/ui/button.js";
14
+ import { Switch } from "../../components/ui/switch.js";
15
+ import { dispatchAccessDescriptor } from "../../shared/app-roles.js";
16
+ import { DISPATCH_CONNECT_APPS_FLAG } from "../../shared/feature-flags.js";
17
+ const coreMembersPage = CORE_SETTINGS_PAGES.find((page) => page.id === "members");
18
+ if (!coreMembersPage) {
19
+ throw new Error("Core Settings has no members page for Dispatch app roles");
20
+ }
21
+ function DispatchMembersSettingsPage() {
22
+ return _jsx(OrgMembersPage, { appRoles: dispatchAccessDescriptor });
23
+ }
24
+ // The redesigned Settings shows Members from core; Dispatch's replaces it so
25
+ // the app-role column stays.
26
+ registerSettingsPages([
27
+ { ...coreMembersPage, component: DispatchMembersSettingsPage },
28
+ ]);
29
+ export function meta() {
30
+ return [{ title: "Settings - Dispatch" }];
31
+ }
32
+ /** The template route supplies the app's own changelog. */
33
+ export function DispatchSettingsPage({ changelog }) {
34
+ const t = useT();
35
+ const connectAppsEnabled = useFeatureFlag(DISPATCH_CONNECT_APPS_FLAG.key);
36
+ // Core Preferences owns the interface language in the redesigned Settings,
37
+ // whose Dispatch General page shows `generalGroups` instead of `general`.
38
+ const redesign = useFeatureFlagState(SETTINGS_REDESIGN_FLAG.key).enabled;
39
+ const agentSettingsTabs = useAgentSettingsTabs({
40
+ usageAppId: "dispatch",
41
+ usageViewAllHref: "/admin/metrics",
42
+ organizationContent: (_jsx("div", { className: "mx-auto w-full max-w-3xl", children: _jsx(TeamPage, { showTitle: false, appRoles: dispatchAccessDescriptor, createOrgDescription: "Set up a team to share dispatch destinations and approvals with your colleagues." }) })),
43
+ });
44
+ const settingsTabs = [
45
+ ...agentSettingsTabs,
46
+ {
47
+ id: "admin",
48
+ label: t("dispatch.nav.admin", { defaultValue: "Admin" }),
49
+ icon: IconShield,
50
+ group: "Admin",
51
+ href: "/admin",
52
+ content: null,
53
+ },
54
+ ];
55
+ const [chatFirstModeState] = useState(() => readChatFirstModeState());
56
+ const [chatFirstMode, setChatFirstMode] = useState(() => chatFirstModeState.enabled);
57
+ const [chatFirstStorageNotice, setChatFirstStorageNotice] = useState(chatFirstModeState.availability === "unavailable"
58
+ ? t("settings.chatFirstStorageUnavailable")
59
+ : null);
60
+ function updateChatFirstMode(enabled) {
61
+ const result = writeChatFirstMode(enabled);
62
+ if (!result.ok) {
63
+ setChatFirstStorageNotice(t("settings.chatFirstStorageBlocked"));
64
+ return;
65
+ }
66
+ setChatFirstStorageNotice(null);
67
+ setChatFirstMode(enabled);
68
+ window.dispatchEvent(new CustomEvent(CHAT_FIRST_MODE_CHANGED_EVENT, {
69
+ detail: { enabled },
70
+ }));
71
+ }
72
+ const generalSearchEntries = useMemo(() => [
73
+ ...(redesign
74
+ ? []
75
+ : [
76
+ {
77
+ id: "dispatch-language",
78
+ label: t("settings.languageTitle"),
79
+ keywords: "language locale translation i18n",
80
+ hash: "language",
81
+ },
82
+ ]),
83
+ {
84
+ id: "dispatch-workspace",
85
+ label: redesign
86
+ ? t("settings.resourcesTitle")
87
+ : t("settings.workspaceTitle"),
88
+ keywords: "workspace resources integrations vault destinations",
89
+ hash: "workspace-resources",
90
+ },
91
+ {
92
+ id: "dispatch-chat-first",
93
+ label: t("settings.chatFirstTitle"),
94
+ keywords: "chat first codex t3 apps pane navigation",
95
+ hash: "chat-first",
96
+ },
97
+ ], [redesign, t]);
98
+ const chatFirstSwitch = (_jsx(Switch, { "aria-label": t("settings.chatFirstAriaLabel"), checked: chatFirstMode, onCheckedChange: updateChatFirstMode }));
99
+ const chatFirstStorageAlert = chatFirstStorageNotice ? (_jsx("p", { className: "text-sm text-destructive", role: "alert", children: chatFirstStorageNotice })) : null;
100
+ const connectAppsRow = connectAppsEnabled ? (_jsx(SettingsRow, { id: "connect-apps", label: t("settings.connectApps"), description: t("settings.connectAppsDescription"), control: _jsx(Button, { variant: "outline", asChild: true, children: _jsx(Link, { to: "/connect", children: t("settings.openConnectApps") }) }) })) : null;
101
+ const resourceSettingsButton = (_jsx(Button, { variant: "outline", asChild: true, children: _jsx(Link, { to: "/workspace", children: t("settings.openResourceSettings") }) }));
102
+ return (_jsx(SettingsTabsPage, { account: _jsx(AccountSettingsCard, {}), extraTabs: settingsTabs, generalSearchEntries: generalSearchEntries, general: _jsxs("div", { className: "mx-auto w-full max-w-2xl space-y-6", children: [_jsx("p", { className: "text-sm leading-6 text-muted-foreground", children: t("settings.description") }), _jsxs(SettingsGroup, { children: [_jsx(SettingsRow, { id: "language", label: t("settings.languageTitle"), description: t("settings.languageDescription"), control: _jsx("div", { className: "w-56", children: _jsx(LanguagePicker, { label: t("settings.languageLabel") }) }) }), _jsx(SettingsRow, { id: "workspace-resources", label: t("settings.workspaceTitle"), description: t("settings.workspaceDescription"), control: resourceSettingsButton }), connectAppsRow] }), _jsx(SettingsGroup, { id: "chat-first", children: _jsxs(SettingsRow, { label: t("settings.chatFirstTitle"), description: t("settings.chatFirstDescription"), control: chatFirstSwitch, children: [_jsx("p", { className: "text-sm leading-6 text-muted-foreground", children: t("settings.chatFirstSessionWatchDescription") }), chatFirstStorageAlert] }) })] }), generalGroups: _jsxs(SettingsGroup, { id: "workspace", title: t("settings.workspaceTitle"), children: [_jsx(SettingsRow, { id: "chat-first", label: t("settings.chatFirstTitle"), description: t("settings.chatFirstDescription"), control: chatFirstSwitch, children: chatFirstStorageAlert }), _jsx(SettingsRow, { id: "workspace-resources", label: t("settings.resourcesTitle"), description: t("settings.workspaceDescription"), control: resourceSettingsButton }), connectAppsRow] }), whatsNew: _jsx("div", { className: "mx-auto w-full max-w-2xl", children: _jsx(ChangelogSettingsCard, { markdown: changelog }) }), whatsNewMarkdown: changelog }));
103
+ }
104
+ //# sourceMappingURL=settings-page.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"settings-page.js","sourceRoot":"","sources":["../../../src/routes/pages/settings-page.tsx"],"names":[],"mappings":"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","sourcesContent":["import {\n CHAT_FIRST_MODE_CHANGED_EVENT,\n readChatFirstModeState,\n writeChatFirstMode,\n} from \"@agent-native/core/client/agent-chat\";\nimport {\n useFeatureFlag,\n useFeatureFlagState,\n} from \"@agent-native/core/client/feature-flags\";\nimport { useT } from \"@agent-native/core/client/i18n\";\nimport { SETTINGS_REDESIGN_FLAG } from \"@agent-native/core/feature-flags/registry\";\nimport { ChangelogSettingsCard } from \"@agent-native/toolkit/app/changelog\";\nimport { OrgMembersPage, TeamPage } from \"@agent-native/toolkit/app/org\";\nimport {\n AccountSettingsCard,\n CORE_SETTINGS_PAGES,\n registerSettingsPages,\n SettingsGroup,\n SettingsRow,\n SettingsTabsPage,\n useAgentSettingsTabs,\n type SettingsSearchEntry,\n} from \"@agent-native/toolkit/app/settings\";\nimport { LanguagePicker } from \"@agent-native/toolkit/app/shared\";\nimport { IconShield } from \"@tabler/icons-react\";\nimport { useMemo, useState } from \"react\";\nimport { Link } from \"react-router\";\n\nimport { Button } from \"../../components/ui/button\";\nimport { Switch } from \"../../components/ui/switch\";\nimport { dispatchAccessDescriptor } from \"../../shared/app-roles.js\";\nimport { DISPATCH_CONNECT_APPS_FLAG } from \"../../shared/feature-flags.js\";\n\nconst coreMembersPage = CORE_SETTINGS_PAGES.find(\n (page) => page.id === \"members\",\n);\nif (!coreMembersPage) {\n throw new Error(\"Core Settings has no members page for Dispatch app roles\");\n}\n\nfunction DispatchMembersSettingsPage() {\n return <OrgMembersPage appRoles={dispatchAccessDescriptor} />;\n}\n\n// The redesigned Settings shows Members from core; Dispatch's replaces it so\n// the app-role column stays.\nregisterSettingsPages([\n { ...coreMembersPage, component: DispatchMembersSettingsPage },\n]);\n\nexport function meta() {\n return [{ title: \"Settings - Dispatch\" }];\n}\n\nexport interface DispatchSettingsPageProps {\n /** Raw CHANGELOG.md behind What's new. */\n changelog: string;\n}\n\n/** The template route supplies the app's own changelog. */\nexport function DispatchSettingsPage({ changelog }: DispatchSettingsPageProps) {\n const t = useT();\n const connectAppsEnabled = useFeatureFlag(DISPATCH_CONNECT_APPS_FLAG.key);\n // Core Preferences owns the interface language in the redesigned Settings,\n // whose Dispatch General page shows `generalGroups` instead of `general`.\n const redesign = useFeatureFlagState(SETTINGS_REDESIGN_FLAG.key).enabled;\n const agentSettingsTabs = useAgentSettingsTabs({\n usageAppId: \"dispatch\",\n usageViewAllHref: \"/admin/metrics\",\n organizationContent: (\n <div className=\"mx-auto w-full max-w-3xl\">\n <TeamPage\n showTitle={false}\n appRoles={dispatchAccessDescriptor}\n createOrgDescription=\"Set up a team to share dispatch destinations and approvals with your colleagues.\"\n />\n </div>\n ),\n });\n const settingsTabs = [\n ...agentSettingsTabs,\n {\n id: \"admin\",\n label: t(\"dispatch.nav.admin\", { defaultValue: \"Admin\" }),\n icon: IconShield,\n group: \"Admin\",\n href: \"/admin\",\n content: null,\n },\n ];\n const [chatFirstModeState] = useState(() => readChatFirstModeState());\n const [chatFirstMode, setChatFirstMode] = useState(\n () => chatFirstModeState.enabled,\n );\n const [chatFirstStorageNotice, setChatFirstStorageNotice] = useState<\n string | null\n >(\n chatFirstModeState.availability === \"unavailable\"\n ? t(\"settings.chatFirstStorageUnavailable\")\n : null,\n );\n\n function updateChatFirstMode(enabled: boolean) {\n const result = writeChatFirstMode(enabled);\n if (!result.ok) {\n setChatFirstStorageNotice(t(\"settings.chatFirstStorageBlocked\"));\n return;\n }\n setChatFirstStorageNotice(null);\n setChatFirstMode(enabled);\n window.dispatchEvent(\n new CustomEvent(CHAT_FIRST_MODE_CHANGED_EVENT, {\n detail: { enabled },\n }),\n );\n }\n\n const generalSearchEntries = useMemo<SettingsSearchEntry[]>(\n () => [\n ...(redesign\n ? []\n : [\n {\n id: \"dispatch-language\",\n label: t(\"settings.languageTitle\"),\n keywords: \"language locale translation i18n\",\n hash: \"language\",\n },\n ]),\n {\n id: \"dispatch-workspace\",\n label: redesign\n ? t(\"settings.resourcesTitle\")\n : t(\"settings.workspaceTitle\"),\n keywords: \"workspace resources integrations vault destinations\",\n hash: \"workspace-resources\",\n },\n {\n id: \"dispatch-chat-first\",\n label: t(\"settings.chatFirstTitle\"),\n keywords: \"chat first codex t3 apps pane navigation\",\n hash: \"chat-first\",\n },\n ],\n [redesign, t],\n );\n\n const chatFirstSwitch = (\n <Switch\n aria-label={t(\"settings.chatFirstAriaLabel\")}\n checked={chatFirstMode}\n onCheckedChange={updateChatFirstMode}\n />\n );\n const chatFirstStorageAlert = chatFirstStorageNotice ? (\n <p className=\"text-sm text-destructive\" role=\"alert\">\n {chatFirstStorageNotice}\n </p>\n ) : null;\n const connectAppsRow = connectAppsEnabled ? (\n <SettingsRow\n id=\"connect-apps\"\n label={t(\"settings.connectApps\")}\n description={t(\"settings.connectAppsDescription\")}\n control={\n <Button variant=\"outline\" asChild>\n <Link to=\"/connect\">{t(\"settings.openConnectApps\")}</Link>\n </Button>\n }\n />\n ) : null;\n const resourceSettingsButton = (\n <Button variant=\"outline\" asChild>\n <Link to=\"/workspace\">{t(\"settings.openResourceSettings\")}</Link>\n </Button>\n );\n\n return (\n <SettingsTabsPage\n account={<AccountSettingsCard />}\n extraTabs={settingsTabs}\n generalSearchEntries={generalSearchEntries}\n general={\n <div className=\"mx-auto w-full max-w-2xl space-y-6\">\n <p className=\"text-sm leading-6 text-muted-foreground\">\n {t(\"settings.description\")}\n </p>\n\n <SettingsGroup>\n <SettingsRow\n id=\"language\"\n label={t(\"settings.languageTitle\")}\n description={t(\"settings.languageDescription\")}\n control={\n <div className=\"w-56\">\n <LanguagePicker label={t(\"settings.languageLabel\")} />\n </div>\n }\n />\n <SettingsRow\n id=\"workspace-resources\"\n label={t(\"settings.workspaceTitle\")}\n description={t(\"settings.workspaceDescription\")}\n control={resourceSettingsButton}\n />\n {connectAppsRow}\n </SettingsGroup>\n\n <SettingsGroup id=\"chat-first\">\n <SettingsRow\n label={t(\"settings.chatFirstTitle\")}\n description={t(\"settings.chatFirstDescription\")}\n control={chatFirstSwitch}\n >\n <p className=\"text-sm leading-6 text-muted-foreground\">\n {t(\"settings.chatFirstSessionWatchDescription\")}\n </p>\n {chatFirstStorageAlert}\n </SettingsRow>\n </SettingsGroup>\n </div>\n }\n generalGroups={\n <SettingsGroup id=\"workspace\" title={t(\"settings.workspaceTitle\")}>\n <SettingsRow\n id=\"chat-first\"\n label={t(\"settings.chatFirstTitle\")}\n description={t(\"settings.chatFirstDescription\")}\n control={chatFirstSwitch}\n >\n {chatFirstStorageAlert}\n </SettingsRow>\n <SettingsRow\n id=\"workspace-resources\"\n label={t(\"settings.resourcesTitle\")}\n description={t(\"settings.workspaceDescription\")}\n control={resourceSettingsButton}\n />\n {connectAppsRow}\n </SettingsGroup>\n }\n whatsNew={\n <div className=\"mx-auto w-full max-w-2xl\">\n <ChangelogSettingsCard markdown={changelog} />\n </div>\n }\n whatsNewMarkdown={changelog}\n />\n );\n}\n"]}
@@ -1,14 +1,6 @@
1
- export declare function meta(): {
2
- title: string;
3
- }[];
4
- export interface DispatchSettingsPageProps {
5
- /** Raw CHANGELOG.md behind What's new. */
6
- changelog: string;
7
- }
8
- /**
9
- * Dispatch's Settings. The template route renders it with the app's own
10
- * changelog; `dispatchRoutes` consumers get the default export.
11
- */
12
- export declare function DispatchSettingsPage({ changelog }: DispatchSettingsPageProps): import("node_modules/@types/react").JSX.Element;
1
+ import { DispatchSettingsPage } from "./settings-page.js";
2
+ export { DispatchSettingsPage };
3
+ export type { DispatchSettingsPageProps } from "./settings-page.js";
4
+ export { meta } from "./settings-page.js";
13
5
  export default function SettingsRoute(): import("node_modules/@types/react").JSX.Element;
14
6
  //# sourceMappingURL=settings.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"settings.d.ts","sourceRoot":"","sources":["../../../src/routes/pages/settings.tsx"],"names":[],"mappings":"AAmDA,wBAAgB,IAAI;;IAEnB;AAED,MAAM,WAAW,yBAAyB;IACxC,0CAA0C;IAC1C,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,EAAE,SAAS,EAAE,EAAE,yBAAyB,mDA6L5E;AAED,MAAM,CAAC,OAAO,UAAU,aAAa,oDAEpC"}
1
+ {"version":3,"file":"settings.d.ts","sourceRoot":"","sources":["../../../src/routes/pages/settings.tsx"],"names":[],"mappings":"AACA,OAAO,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAE1D,OAAO,EAAE,oBAAoB,EAAE,CAAC;AAChC,YAAY,EAAE,yBAAyB,EAAE,MAAM,oBAAoB,CAAC;AACpE,OAAO,EAAE,IAAI,EAAE,MAAM,oBAAoB,CAAC;AAE1C,MAAM,CAAC,OAAO,UAAU,aAAa,oDAEpC"}
@@ -1,110 +1,8 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { CHAT_FIRST_MODE_CHANGED_EVENT, readChatFirstModeState, writeChatFirstMode, } from "@agent-native/core/client/agent-chat";
3
- import { useFeatureFlag, useFeatureFlagState, } from "@agent-native/core/client/feature-flags";
4
- import { useT } from "@agent-native/core/client/i18n";
5
- import { SETTINGS_REDESIGN_FLAG } from "@agent-native/core/feature-flags/registry";
6
- import { ChangelogSettingsCard } from "@agent-native/toolkit/app/changelog";
7
- import { OrgMembersPage, TeamPage } from "@agent-native/toolkit/app/org";
8
- import { AccountSettingsCard, CORE_SETTINGS_PAGES, registerSettingsPages, SettingsGroup, SettingsRow, SettingsTabsPage, useAgentSettingsTabs, } from "@agent-native/toolkit/app/settings";
9
- import { LanguagePicker } from "@agent-native/toolkit/app/shared";
10
- import { IconShield } from "@tabler/icons-react";
11
- import { useMemo, useState } from "react";
12
- import { Link } from "react-router";
1
+ import { jsx as _jsx } from "react/jsx-runtime";
13
2
  import packageChangelog from "../../../CHANGELOG.md?raw";
14
- import { Button } from "../../components/ui/button.js";
15
- import { Switch } from "../../components/ui/switch.js";
16
- import { dispatchAccessDescriptor } from "../../shared/app-roles.js";
17
- import { DISPATCH_CONNECT_APPS_FLAG } from "../../shared/feature-flags.js";
18
- const coreMembersPage = CORE_SETTINGS_PAGES.find((page) => page.id === "members");
19
- if (!coreMembersPage) {
20
- throw new Error("Core Settings has no members page for Dispatch app roles");
21
- }
22
- function DispatchMembersSettingsPage() {
23
- return _jsx(OrgMembersPage, { appRoles: dispatchAccessDescriptor });
24
- }
25
- // The redesigned Settings shows Members from core; Dispatch's replaces it so
26
- // the app-role column stays.
27
- registerSettingsPages([
28
- { ...coreMembersPage, component: DispatchMembersSettingsPage },
29
- ]);
30
- export function meta() {
31
- return [{ title: "Settings - Dispatch" }];
32
- }
33
- /**
34
- * Dispatch's Settings. The template route renders it with the app's own
35
- * changelog; `dispatchRoutes` consumers get the default export.
36
- */
37
- export function DispatchSettingsPage({ changelog }) {
38
- const t = useT();
39
- const connectAppsEnabled = useFeatureFlag(DISPATCH_CONNECT_APPS_FLAG.key);
40
- // Core Preferences owns the interface language in the redesigned Settings,
41
- // whose Dispatch General page shows `generalGroups` instead of `general`.
42
- const redesign = useFeatureFlagState(SETTINGS_REDESIGN_FLAG.key).enabled;
43
- const agentSettingsTabs = useAgentSettingsTabs({
44
- usageAppId: "dispatch",
45
- usageViewAllHref: "/admin/metrics",
46
- organizationContent: (_jsx("div", { className: "mx-auto w-full max-w-3xl", children: _jsx(TeamPage, { showTitle: false, appRoles: dispatchAccessDescriptor, createOrgDescription: "Set up a team to share dispatch destinations and approvals with your colleagues." }) })),
47
- });
48
- const settingsTabs = [
49
- ...agentSettingsTabs,
50
- {
51
- id: "admin",
52
- label: t("dispatch.nav.admin", { defaultValue: "Admin" }),
53
- icon: IconShield,
54
- group: "Admin",
55
- href: "/admin",
56
- content: null,
57
- },
58
- ];
59
- const [chatFirstModeState] = useState(() => readChatFirstModeState());
60
- const [chatFirstMode, setChatFirstMode] = useState(() => chatFirstModeState.enabled);
61
- const [chatFirstStorageNotice, setChatFirstStorageNotice] = useState(chatFirstModeState.availability === "unavailable"
62
- ? t("settings.chatFirstStorageUnavailable")
63
- : null);
64
- function updateChatFirstMode(enabled) {
65
- const result = writeChatFirstMode(enabled);
66
- if (!result.ok) {
67
- setChatFirstStorageNotice(t("settings.chatFirstStorageBlocked"));
68
- return;
69
- }
70
- setChatFirstStorageNotice(null);
71
- setChatFirstMode(enabled);
72
- window.dispatchEvent(new CustomEvent(CHAT_FIRST_MODE_CHANGED_EVENT, {
73
- detail: { enabled },
74
- }));
75
- }
76
- const generalSearchEntries = useMemo(() => [
77
- ...(redesign
78
- ? []
79
- : [
80
- {
81
- id: "dispatch-language",
82
- label: t("settings.languageTitle"),
83
- keywords: "language locale translation i18n",
84
- hash: "language",
85
- },
86
- ]),
87
- {
88
- id: "dispatch-workspace",
89
- label: redesign
90
- ? t("settings.resourcesTitle")
91
- : t("settings.workspaceTitle"),
92
- keywords: "workspace resources integrations vault destinations",
93
- hash: "workspace-resources",
94
- },
95
- {
96
- id: "dispatch-chat-first",
97
- label: t("settings.chatFirstTitle"),
98
- keywords: "chat first codex t3 apps pane navigation",
99
- hash: "chat-first",
100
- },
101
- ], [redesign, t]);
102
- const chatFirstSwitch = (_jsx(Switch, { "aria-label": t("settings.chatFirstAriaLabel"), checked: chatFirstMode, onCheckedChange: updateChatFirstMode }));
103
- const chatFirstStorageAlert = chatFirstStorageNotice ? (_jsx("p", { className: "text-sm text-destructive", role: "alert", children: chatFirstStorageNotice })) : null;
104
- const connectAppsRow = connectAppsEnabled ? (_jsx(SettingsRow, { id: "connect-apps", label: t("settings.connectApps"), description: t("settings.connectAppsDescription"), control: _jsx(Button, { variant: "outline", asChild: true, children: _jsx(Link, { to: "/connect", children: t("settings.openConnectApps") }) }) })) : null;
105
- const resourceSettingsButton = (_jsx(Button, { variant: "outline", asChild: true, children: _jsx(Link, { to: "/workspace", children: t("settings.openResourceSettings") }) }));
106
- return (_jsx(SettingsTabsPage, { account: _jsx(AccountSettingsCard, {}), extraTabs: settingsTabs, generalSearchEntries: generalSearchEntries, general: _jsxs("div", { className: "mx-auto w-full max-w-2xl space-y-6", children: [_jsx("p", { className: "text-sm leading-6 text-muted-foreground", children: t("settings.description") }), _jsxs(SettingsGroup, { children: [_jsx(SettingsRow, { id: "language", label: t("settings.languageTitle"), description: t("settings.languageDescription"), control: _jsx("div", { className: "w-56", children: _jsx(LanguagePicker, { label: t("settings.languageLabel") }) }) }), _jsx(SettingsRow, { id: "workspace-resources", label: t("settings.workspaceTitle"), description: t("settings.workspaceDescription"), control: resourceSettingsButton }), connectAppsRow] }), _jsx(SettingsGroup, { id: "chat-first", children: _jsxs(SettingsRow, { label: t("settings.chatFirstTitle"), description: t("settings.chatFirstDescription"), control: chatFirstSwitch, children: [_jsx("p", { className: "text-sm leading-6 text-muted-foreground", children: t("settings.chatFirstSessionWatchDescription") }), chatFirstStorageAlert] }) })] }), generalGroups: _jsxs(SettingsGroup, { id: "workspace", title: t("settings.workspaceTitle"), children: [_jsx(SettingsRow, { id: "chat-first", label: t("settings.chatFirstTitle"), description: t("settings.chatFirstDescription"), control: chatFirstSwitch, children: chatFirstStorageAlert }), _jsx(SettingsRow, { id: "workspace-resources", label: t("settings.resourcesTitle"), description: t("settings.workspaceDescription"), control: resourceSettingsButton }), connectAppsRow] }), whatsNew: _jsx("div", { className: "mx-auto w-full max-w-2xl", children: _jsx(ChangelogSettingsCard, { markdown: changelog }) }), whatsNewMarkdown: changelog }));
107
- }
3
+ import { DispatchSettingsPage } from "./settings-page.js";
4
+ export { DispatchSettingsPage };
5
+ export { meta } from "./settings-page.js";
108
6
  export default function SettingsRoute() {
109
7
  return _jsx(DispatchSettingsPage, { changelog: packageChangelog });
110
8
  }
@@ -1 +1 @@
1
- {"version":3,"file":"settings.js","sourceRoot":"","sources":["../../../src/routes/pages/settings.tsx"],"names":[],"mappings":"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","sourcesContent":["import {\n CHAT_FIRST_MODE_CHANGED_EVENT,\n readChatFirstModeState,\n writeChatFirstMode,\n} from \"@agent-native/core/client/agent-chat\";\nimport {\n useFeatureFlag,\n useFeatureFlagState,\n} from \"@agent-native/core/client/feature-flags\";\nimport { useT } from \"@agent-native/core/client/i18n\";\nimport { SETTINGS_REDESIGN_FLAG } from \"@agent-native/core/feature-flags/registry\";\nimport { ChangelogSettingsCard } from \"@agent-native/toolkit/app/changelog\";\nimport { OrgMembersPage, TeamPage } from \"@agent-native/toolkit/app/org\";\nimport {\n AccountSettingsCard,\n CORE_SETTINGS_PAGES,\n registerSettingsPages,\n SettingsGroup,\n SettingsRow,\n SettingsTabsPage,\n useAgentSettingsTabs,\n type SettingsSearchEntry,\n} from \"@agent-native/toolkit/app/settings\";\nimport { LanguagePicker } from \"@agent-native/toolkit/app/shared\";\nimport { IconShield } from \"@tabler/icons-react\";\nimport { useMemo, useState } from \"react\";\nimport { Link } from \"react-router\";\n\nimport packageChangelog from \"../../../CHANGELOG.md?raw\";\nimport { Button } from \"../../components/ui/button\";\nimport { Switch } from \"../../components/ui/switch\";\nimport { dispatchAccessDescriptor } from \"../../shared/app-roles.js\";\nimport { DISPATCH_CONNECT_APPS_FLAG } from \"../../shared/feature-flags.js\";\n\nconst coreMembersPage = CORE_SETTINGS_PAGES.find(\n (page) => page.id === \"members\",\n);\nif (!coreMembersPage) {\n throw new Error(\"Core Settings has no members page for Dispatch app roles\");\n}\n\nfunction DispatchMembersSettingsPage() {\n return <OrgMembersPage appRoles={dispatchAccessDescriptor} />;\n}\n\n// The redesigned Settings shows Members from core; Dispatch's replaces it so\n// the app-role column stays.\nregisterSettingsPages([\n { ...coreMembersPage, component: DispatchMembersSettingsPage },\n]);\n\nexport function meta() {\n return [{ title: \"Settings - Dispatch\" }];\n}\n\nexport interface DispatchSettingsPageProps {\n /** Raw CHANGELOG.md behind What's new. */\n changelog: string;\n}\n\n/**\n * Dispatch's Settings. The template route renders it with the app's own\n * changelog; `dispatchRoutes` consumers get the default export.\n */\nexport function DispatchSettingsPage({ changelog }: DispatchSettingsPageProps) {\n const t = useT();\n const connectAppsEnabled = useFeatureFlag(DISPATCH_CONNECT_APPS_FLAG.key);\n // Core Preferences owns the interface language in the redesigned Settings,\n // whose Dispatch General page shows `generalGroups` instead of `general`.\n const redesign = useFeatureFlagState(SETTINGS_REDESIGN_FLAG.key).enabled;\n const agentSettingsTabs = useAgentSettingsTabs({\n usageAppId: \"dispatch\",\n usageViewAllHref: \"/admin/metrics\",\n organizationContent: (\n <div className=\"mx-auto w-full max-w-3xl\">\n <TeamPage\n showTitle={false}\n appRoles={dispatchAccessDescriptor}\n createOrgDescription=\"Set up a team to share dispatch destinations and approvals with your colleagues.\"\n />\n </div>\n ),\n });\n const settingsTabs = [\n ...agentSettingsTabs,\n {\n id: \"admin\",\n label: t(\"dispatch.nav.admin\", { defaultValue: \"Admin\" }),\n icon: IconShield,\n group: \"Admin\",\n href: \"/admin\",\n content: null,\n },\n ];\n const [chatFirstModeState] = useState(() => readChatFirstModeState());\n const [chatFirstMode, setChatFirstMode] = useState(\n () => chatFirstModeState.enabled,\n );\n const [chatFirstStorageNotice, setChatFirstStorageNotice] = useState<\n string | null\n >(\n chatFirstModeState.availability === \"unavailable\"\n ? t(\"settings.chatFirstStorageUnavailable\")\n : null,\n );\n\n function updateChatFirstMode(enabled: boolean) {\n const result = writeChatFirstMode(enabled);\n if (!result.ok) {\n setChatFirstStorageNotice(t(\"settings.chatFirstStorageBlocked\"));\n return;\n }\n setChatFirstStorageNotice(null);\n setChatFirstMode(enabled);\n window.dispatchEvent(\n new CustomEvent(CHAT_FIRST_MODE_CHANGED_EVENT, {\n detail: { enabled },\n }),\n );\n }\n\n const generalSearchEntries = useMemo<SettingsSearchEntry[]>(\n () => [\n ...(redesign\n ? []\n : [\n {\n id: \"dispatch-language\",\n label: t(\"settings.languageTitle\"),\n keywords: \"language locale translation i18n\",\n hash: \"language\",\n },\n ]),\n {\n id: \"dispatch-workspace\",\n label: redesign\n ? t(\"settings.resourcesTitle\")\n : t(\"settings.workspaceTitle\"),\n keywords: \"workspace resources integrations vault destinations\",\n hash: \"workspace-resources\",\n },\n {\n id: \"dispatch-chat-first\",\n label: t(\"settings.chatFirstTitle\"),\n keywords: \"chat first codex t3 apps pane navigation\",\n hash: \"chat-first\",\n },\n ],\n [redesign, t],\n );\n\n const chatFirstSwitch = (\n <Switch\n aria-label={t(\"settings.chatFirstAriaLabel\")}\n checked={chatFirstMode}\n onCheckedChange={updateChatFirstMode}\n />\n );\n const chatFirstStorageAlert = chatFirstStorageNotice ? (\n <p className=\"text-sm text-destructive\" role=\"alert\">\n {chatFirstStorageNotice}\n </p>\n ) : null;\n const connectAppsRow = connectAppsEnabled ? (\n <SettingsRow\n id=\"connect-apps\"\n label={t(\"settings.connectApps\")}\n description={t(\"settings.connectAppsDescription\")}\n control={\n <Button variant=\"outline\" asChild>\n <Link to=\"/connect\">{t(\"settings.openConnectApps\")}</Link>\n </Button>\n }\n />\n ) : null;\n const resourceSettingsButton = (\n <Button variant=\"outline\" asChild>\n <Link to=\"/workspace\">{t(\"settings.openResourceSettings\")}</Link>\n </Button>\n );\n\n return (\n <SettingsTabsPage\n account={<AccountSettingsCard />}\n extraTabs={settingsTabs}\n generalSearchEntries={generalSearchEntries}\n general={\n <div className=\"mx-auto w-full max-w-2xl space-y-6\">\n <p className=\"text-sm leading-6 text-muted-foreground\">\n {t(\"settings.description\")}\n </p>\n\n <SettingsGroup>\n <SettingsRow\n id=\"language\"\n label={t(\"settings.languageTitle\")}\n description={t(\"settings.languageDescription\")}\n control={\n <div className=\"w-56\">\n <LanguagePicker label={t(\"settings.languageLabel\")} />\n </div>\n }\n />\n <SettingsRow\n id=\"workspace-resources\"\n label={t(\"settings.workspaceTitle\")}\n description={t(\"settings.workspaceDescription\")}\n control={resourceSettingsButton}\n />\n {connectAppsRow}\n </SettingsGroup>\n\n <SettingsGroup id=\"chat-first\">\n <SettingsRow\n label={t(\"settings.chatFirstTitle\")}\n description={t(\"settings.chatFirstDescription\")}\n control={chatFirstSwitch}\n >\n <p className=\"text-sm leading-6 text-muted-foreground\">\n {t(\"settings.chatFirstSessionWatchDescription\")}\n </p>\n {chatFirstStorageAlert}\n </SettingsRow>\n </SettingsGroup>\n </div>\n }\n generalGroups={\n <SettingsGroup id=\"workspace\" title={t(\"settings.workspaceTitle\")}>\n <SettingsRow\n id=\"chat-first\"\n label={t(\"settings.chatFirstTitle\")}\n description={t(\"settings.chatFirstDescription\")}\n control={chatFirstSwitch}\n >\n {chatFirstStorageAlert}\n </SettingsRow>\n <SettingsRow\n id=\"workspace-resources\"\n label={t(\"settings.resourcesTitle\")}\n description={t(\"settings.workspaceDescription\")}\n control={resourceSettingsButton}\n />\n {connectAppsRow}\n </SettingsGroup>\n }\n whatsNew={\n <div className=\"mx-auto w-full max-w-2xl\">\n <ChangelogSettingsCard markdown={changelog} />\n </div>\n }\n whatsNewMarkdown={changelog}\n />\n );\n}\n\nexport default function SettingsRoute() {\n return <DispatchSettingsPage changelog={packageChangelog} />;\n}\n"]}
1
+ {"version":3,"file":"settings.js","sourceRoot":"","sources":["../../../src/routes/pages/settings.tsx"],"names":[],"mappings":";AAAA,OAAO,gBAAgB,MAAM,2BAA2B,CAAC;AACzD,OAAO,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAE1D,OAAO,EAAE,oBAAoB,EAAE,CAAC;AAEhC,OAAO,EAAE,IAAI,EAAE,MAAM,oBAAoB,CAAC;AAE1C,MAAM,CAAC,OAAO,UAAU,aAAa;IACnC,OAAO,KAAC,oBAAoB,IAAC,SAAS,EAAE,gBAAgB,GAAI,CAAC;AAC/D,CAAC","sourcesContent":["import packageChangelog from \"../../../CHANGELOG.md?raw\";\nimport { DispatchSettingsPage } from \"./settings-page.js\";\n\nexport { DispatchSettingsPage };\nexport type { DispatchSettingsPageProps } from \"./settings-page.js\";\nexport { meta } from \"./settings-page.js\";\n\nexport default function SettingsRoute() {\n return <DispatchSettingsPage changelog={packageChangelog} />;\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agent-native/dispatch",
3
- "version": "0.40.2",
3
+ "version": "0.40.4-nightly-20260930124743",
4
4
  "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.",
5
5
  "homepage": "https://github.com/BuilderIO/agent-native#readme",
6
6
  "bugs": {
@@ -89,7 +89,7 @@
89
89
  "tailwind-merge": "^3.5.0",
90
90
  "vaul": "^1.1.2",
91
91
  "zod": "^4.3.6",
92
- "@agent-native/toolkit": "0.198.1"
92
+ "@agent-native/toolkit": "0.198.3-nightly-20260930124743"
93
93
  },
94
94
  "devDependencies": {
95
95
  "@react-router/dev": "^8.1.0",
@@ -103,10 +103,10 @@
103
103
  "typescript-7": "npm:typescript@^7.0.2",
104
104
  "vite": "8.1.0",
105
105
  "vitest": "^4.1.5",
106
- "@agent-native/core": "0.198.1"
106
+ "@agent-native/core": "0.198.3-nightly-20260930124743"
107
107
  },
108
108
  "peerDependencies": {
109
- "@agent-native/core": ">=0.8.0",
109
+ "@agent-native/core": "0.198.3-nightly-20260930124743",
110
110
  "react": ">=19.2.7",
111
111
  "react-dom": ">=19.2.7",
112
112
  "react-router": ">=8"
@@ -1,3 +1,4 @@
1
+ import { isSettingsPathname } from "@agent-native/toolkit/app/settings";
1
2
  // @vitest-environment happy-dom
2
3
  import React, { act } from "react";
3
4
  import { createRoot, type Root } from "react-dom/client";
@@ -12,7 +13,7 @@ import {
12
13
  dispatchNavLinkTarget,
13
14
  formatThreadAge,
14
15
  isElectronEmbeddedSearch,
15
- isSettingsShellPath,
16
+ isRedesignedSettingsPath,
16
17
  NavContent,
17
18
  renderChatFirstAppSurfaceTab,
18
19
  shouldAutoCollapseDispatchSidebar,
@@ -30,13 +31,27 @@ const clientState = vi.hoisted(() => ({
30
31
  .mockResolvedValue({ startUrl: "about:blank" }),
31
32
  }));
32
33
 
33
- vi.mock("@agent-native/core/client/agent-chat", () => ({
34
+ vi.mock("@agent-native/core/client/agent-chat", async (importOriginal) => ({
35
+ ...(await importOriginal<
36
+ typeof import("@agent-native/core/client/agent-chat")
37
+ >()),
34
38
  navigateWithAgentChatViewTransition: (
35
39
  navigate: (path: string) => void,
36
40
  path: string,
37
41
  ) => navigate(path),
38
42
  useAgentChatHomeHandoff: () => false,
39
43
  useAgentChatHomeHandoffLinks: vi.fn(),
44
+ useChatModels: () => ({
45
+ availableModels: [],
46
+ defaultModel: "auto",
47
+ selectedModel: "auto",
48
+ selectedEngine: "",
49
+ selectedEffort: "medium" as const,
50
+ isLoading: false,
51
+ onModelChange: vi.fn(),
52
+ onEffortChange: vi.fn(),
53
+ refreshEngines: vi.fn(),
54
+ }),
40
55
  useChatThreads: () => ({
41
56
  threads: clientState.threads,
42
57
  activeThreadId: "active-thread",
@@ -46,10 +61,20 @@ vi.mock("@agent-native/core/client/agent-chat", () => ({
46
61
  renameThread: vi.fn(),
47
62
  refreshThreads: vi.fn(),
48
63
  }),
64
+ useChatModels: () => ({
65
+ availableModels: [],
66
+ defaultModel: "auto",
67
+ selectedModel: "auto",
68
+ selectedEngine: "auto",
69
+ selectedEffort: "medium",
70
+ setSelectedModel: vi.fn(),
71
+ }),
49
72
  }));
50
73
 
51
74
  vi.mock("@agent-native/toolkit/app/chat", async (importOriginal) => ({
52
75
  ...(await importOriginal<typeof import("@agent-native/toolkit/app/chat")>()),
76
+ AgentChatSurface: () => null,
77
+ AgentToggleButton: () => null,
53
78
  AgentSidebar: ({ children }: { children: React.ReactNode }) => (
54
79
  <div data-agent-sidebar>{children}</div>
55
80
  ),
@@ -65,9 +90,11 @@ vi.mock("@agent-native/core/client/api-path", () => ({
65
90
  clientState.basePath && path.startsWith("/")
66
91
  ? `${clientState.basePath}${path}`
67
92
  : path,
93
+ frameworkRoutePrefix: () => "",
68
94
  }));
69
95
 
70
- vi.mock("@agent-native/core/client/hooks", () => ({
96
+ vi.mock("@agent-native/core/client/hooks", async (importOriginal) => ({
97
+ ...(await importOriginal<typeof import("@agent-native/core/client/hooks")>()),
71
98
  useActionQuery: (action: string) => ({
72
99
  data:
73
100
  action === "list-workspace-apps" ? clientState.workspaceApps : undefined,
@@ -87,6 +114,7 @@ vi.mock("next-themes", () => ({
87
114
  }));
88
115
 
89
116
  vi.mock("@agent-native/core/client/i18n", () => ({
117
+ useFormatters: () => ({ formatNumber: (value: number) => String(value) }),
90
118
  useT: () => (key: string, values?: Record<string, unknown>) => {
91
119
  const messages: Record<string, string> = {
92
120
  "dispatch.nav.chat": "Chat",
@@ -115,6 +143,10 @@ vi.mock("@agent-native/toolkit/app/shared", async (importOriginal) => ({
115
143
  openCommandMenu: vi.fn(),
116
144
  }));
117
145
 
146
+ vi.mock("../create-app-popover", () => ({
147
+ CreateAppPopover: () => null,
148
+ }));
149
+
118
150
  vi.mock("@agent-native/toolkit/app/feedback", () => ({
119
151
  FeedbackButton: () => <div>Feedback</div>,
120
152
  }));
@@ -204,14 +236,34 @@ describe("Dispatch workspace app sidebar", () => {
204
236
 
205
237
  describe("Dispatch Settings frame", () => {
206
238
  it("drops the Dispatch chrome on Settings", () => {
207
- expect(isSettingsShellPath("/settings")).toBe(true);
208
- expect(isSettingsShellPath("/settings/members")).toBe(true);
209
- expect(isSettingsShellPath("/settings/app")).toBe(true);
239
+ const settingsEnabled = { enabled: true, status: "ready" } as const;
240
+ expect(isRedesignedSettingsPath("/settings", settingsEnabled)).toBe(true);
241
+ expect(isRedesignedSettingsPath("/settings/members", settingsEnabled)).toBe(
242
+ true,
243
+ );
244
+ expect(isRedesignedSettingsPath("/settings/app", settingsEnabled)).toBe(
245
+ true,
246
+ );
247
+ expect(
248
+ isRedesignedSettingsPath("/settings", {
249
+ enabled: false,
250
+ status: "loading",
251
+ }),
252
+ ).toBe(true);
210
253
  });
211
254
 
212
255
  it("keeps the Dispatch chrome off Settings", () => {
213
- expect(isSettingsShellPath("/admin")).toBe(false);
214
- expect(isSettingsShellPath("/apps/mail/settings")).toBe(false);
256
+ const settingsEnabled = { enabled: true, status: "ready" } as const;
257
+ expect(isRedesignedSettingsPath("/admin", settingsEnabled)).toBe(false);
258
+ expect(
259
+ isRedesignedSettingsPath("/apps/mail/settings", settingsEnabled),
260
+ ).toBe(false);
261
+ expect(
262
+ isRedesignedSettingsPath("/settings", {
263
+ enabled: false,
264
+ status: "unavailable",
265
+ }),
266
+ ).toBe(false);
215
267
  });
216
268
  });
217
269
 
@@ -748,8 +800,8 @@ describe("chat-first surface panel toggle stacking", () => {
748
800
  it("keeps the toggle above the mobile full-screen surface panel overlay", async () => {
749
801
  const { ChatFirstSurfacePanelToggle: RealChatFirstSurfacePanelToggle } =
750
802
  await vi.importActual<
751
- typeof import("@agent-native/core/client/agent-chat")
752
- >("@agent-native/core/client/agent-chat");
803
+ typeof import("@agent-native/toolkit/app/chat/chat-first")
804
+ >("@agent-native/toolkit/app/chat/chat-first");
753
805
  const { ChatFirstSurfacePanel } =
754
806
  await import("@agent-native/toolkit/app/chat/chat-first");
755
807
 
@@ -10,7 +10,7 @@ const railState = vi.hoisted(() => ({
10
10
  mutateAsync: vi.fn().mockResolvedValue({ startUrl: "about:blank" }),
11
11
  }));
12
12
 
13
- vi.mock("@agent-native/core/client/agent-chat", () => ({
13
+ vi.mock("@agent-native/toolkit/app/chat", () => ({
14
14
  AgentSidebar: (props: Record<string, unknown>) => {
15
15
  railState.sidebarProps.push(props);
16
16
  return (
@@ -12,7 +12,7 @@ const browserChat = vi.hoisted(() => ({
12
12
  surfaceProps: null as Record<string, unknown> | null,
13
13
  }));
14
14
 
15
- vi.mock("@agent-native/core/client/agent-chat", () => ({
15
+ vi.mock("@agent-native/toolkit/app/chat", () => ({
16
16
  AgentChatSurface: (props: Record<string, unknown>) => {
17
17
  browserChat.surfaceProps = props;
18
18
  return <div data-testid="browser-agent-chat" />;
@@ -0,0 +1,250 @@
1
+ import {
2
+ CHAT_FIRST_MODE_CHANGED_EVENT,
3
+ readChatFirstModeState,
4
+ writeChatFirstMode,
5
+ } from "@agent-native/core/client/agent-chat";
6
+ import {
7
+ useFeatureFlag,
8
+ useFeatureFlagState,
9
+ } from "@agent-native/core/client/feature-flags";
10
+ import { useT } from "@agent-native/core/client/i18n";
11
+ import { SETTINGS_REDESIGN_FLAG } from "@agent-native/core/feature-flags/registry";
12
+ import { ChangelogSettingsCard } from "@agent-native/toolkit/app/changelog";
13
+ import { OrgMembersPage, TeamPage } from "@agent-native/toolkit/app/org";
14
+ import {
15
+ AccountSettingsCard,
16
+ CORE_SETTINGS_PAGES,
17
+ registerSettingsPages,
18
+ SettingsGroup,
19
+ SettingsRow,
20
+ SettingsTabsPage,
21
+ useAgentSettingsTabs,
22
+ type SettingsSearchEntry,
23
+ } from "@agent-native/toolkit/app/settings";
24
+ import { LanguagePicker } from "@agent-native/toolkit/app/shared";
25
+ import { IconShield } from "@tabler/icons-react";
26
+ import { useMemo, useState } from "react";
27
+ import { Link } from "react-router";
28
+
29
+ import { Button } from "../../components/ui/button";
30
+ import { Switch } from "../../components/ui/switch";
31
+ import { dispatchAccessDescriptor } from "../../shared/app-roles.js";
32
+ import { DISPATCH_CONNECT_APPS_FLAG } from "../../shared/feature-flags.js";
33
+
34
+ const coreMembersPage = CORE_SETTINGS_PAGES.find(
35
+ (page) => page.id === "members",
36
+ );
37
+ if (!coreMembersPage) {
38
+ throw new Error("Core Settings has no members page for Dispatch app roles");
39
+ }
40
+
41
+ function DispatchMembersSettingsPage() {
42
+ return <OrgMembersPage appRoles={dispatchAccessDescriptor} />;
43
+ }
44
+
45
+ // The redesigned Settings shows Members from core; Dispatch's replaces it so
46
+ // the app-role column stays.
47
+ registerSettingsPages([
48
+ { ...coreMembersPage, component: DispatchMembersSettingsPage },
49
+ ]);
50
+
51
+ export function meta() {
52
+ return [{ title: "Settings - Dispatch" }];
53
+ }
54
+
55
+ export interface DispatchSettingsPageProps {
56
+ /** Raw CHANGELOG.md behind What's new. */
57
+ changelog: string;
58
+ }
59
+
60
+ /** The template route supplies the app's own changelog. */
61
+ export function DispatchSettingsPage({ changelog }: DispatchSettingsPageProps) {
62
+ const t = useT();
63
+ const connectAppsEnabled = useFeatureFlag(DISPATCH_CONNECT_APPS_FLAG.key);
64
+ // Core Preferences owns the interface language in the redesigned Settings,
65
+ // whose Dispatch General page shows `generalGroups` instead of `general`.
66
+ const redesign = useFeatureFlagState(SETTINGS_REDESIGN_FLAG.key).enabled;
67
+ const agentSettingsTabs = useAgentSettingsTabs({
68
+ usageAppId: "dispatch",
69
+ usageViewAllHref: "/admin/metrics",
70
+ organizationContent: (
71
+ <div className="mx-auto w-full max-w-3xl">
72
+ <TeamPage
73
+ showTitle={false}
74
+ appRoles={dispatchAccessDescriptor}
75
+ createOrgDescription="Set up a team to share dispatch destinations and approvals with your colleagues."
76
+ />
77
+ </div>
78
+ ),
79
+ });
80
+ const settingsTabs = [
81
+ ...agentSettingsTabs,
82
+ {
83
+ id: "admin",
84
+ label: t("dispatch.nav.admin", { defaultValue: "Admin" }),
85
+ icon: IconShield,
86
+ group: "Admin",
87
+ href: "/admin",
88
+ content: null,
89
+ },
90
+ ];
91
+ const [chatFirstModeState] = useState(() => readChatFirstModeState());
92
+ const [chatFirstMode, setChatFirstMode] = useState(
93
+ () => chatFirstModeState.enabled,
94
+ );
95
+ const [chatFirstStorageNotice, setChatFirstStorageNotice] = useState<
96
+ string | null
97
+ >(
98
+ chatFirstModeState.availability === "unavailable"
99
+ ? t("settings.chatFirstStorageUnavailable")
100
+ : null,
101
+ );
102
+
103
+ function updateChatFirstMode(enabled: boolean) {
104
+ const result = writeChatFirstMode(enabled);
105
+ if (!result.ok) {
106
+ setChatFirstStorageNotice(t("settings.chatFirstStorageBlocked"));
107
+ return;
108
+ }
109
+ setChatFirstStorageNotice(null);
110
+ setChatFirstMode(enabled);
111
+ window.dispatchEvent(
112
+ new CustomEvent(CHAT_FIRST_MODE_CHANGED_EVENT, {
113
+ detail: { enabled },
114
+ }),
115
+ );
116
+ }
117
+
118
+ const generalSearchEntries = useMemo<SettingsSearchEntry[]>(
119
+ () => [
120
+ ...(redesign
121
+ ? []
122
+ : [
123
+ {
124
+ id: "dispatch-language",
125
+ label: t("settings.languageTitle"),
126
+ keywords: "language locale translation i18n",
127
+ hash: "language",
128
+ },
129
+ ]),
130
+ {
131
+ id: "dispatch-workspace",
132
+ label: redesign
133
+ ? t("settings.resourcesTitle")
134
+ : t("settings.workspaceTitle"),
135
+ keywords: "workspace resources integrations vault destinations",
136
+ hash: "workspace-resources",
137
+ },
138
+ {
139
+ id: "dispatch-chat-first",
140
+ label: t("settings.chatFirstTitle"),
141
+ keywords: "chat first codex t3 apps pane navigation",
142
+ hash: "chat-first",
143
+ },
144
+ ],
145
+ [redesign, t],
146
+ );
147
+
148
+ const chatFirstSwitch = (
149
+ <Switch
150
+ aria-label={t("settings.chatFirstAriaLabel")}
151
+ checked={chatFirstMode}
152
+ onCheckedChange={updateChatFirstMode}
153
+ />
154
+ );
155
+ const chatFirstStorageAlert = chatFirstStorageNotice ? (
156
+ <p className="text-sm text-destructive" role="alert">
157
+ {chatFirstStorageNotice}
158
+ </p>
159
+ ) : null;
160
+ const connectAppsRow = connectAppsEnabled ? (
161
+ <SettingsRow
162
+ id="connect-apps"
163
+ label={t("settings.connectApps")}
164
+ description={t("settings.connectAppsDescription")}
165
+ control={
166
+ <Button variant="outline" asChild>
167
+ <Link to="/connect">{t("settings.openConnectApps")}</Link>
168
+ </Button>
169
+ }
170
+ />
171
+ ) : null;
172
+ const resourceSettingsButton = (
173
+ <Button variant="outline" asChild>
174
+ <Link to="/workspace">{t("settings.openResourceSettings")}</Link>
175
+ </Button>
176
+ );
177
+
178
+ return (
179
+ <SettingsTabsPage
180
+ account={<AccountSettingsCard />}
181
+ extraTabs={settingsTabs}
182
+ generalSearchEntries={generalSearchEntries}
183
+ general={
184
+ <div className="mx-auto w-full max-w-2xl space-y-6">
185
+ <p className="text-sm leading-6 text-muted-foreground">
186
+ {t("settings.description")}
187
+ </p>
188
+
189
+ <SettingsGroup>
190
+ <SettingsRow
191
+ id="language"
192
+ label={t("settings.languageTitle")}
193
+ description={t("settings.languageDescription")}
194
+ control={
195
+ <div className="w-56">
196
+ <LanguagePicker label={t("settings.languageLabel")} />
197
+ </div>
198
+ }
199
+ />
200
+ <SettingsRow
201
+ id="workspace-resources"
202
+ label={t("settings.workspaceTitle")}
203
+ description={t("settings.workspaceDescription")}
204
+ control={resourceSettingsButton}
205
+ />
206
+ {connectAppsRow}
207
+ </SettingsGroup>
208
+
209
+ <SettingsGroup id="chat-first">
210
+ <SettingsRow
211
+ label={t("settings.chatFirstTitle")}
212
+ description={t("settings.chatFirstDescription")}
213
+ control={chatFirstSwitch}
214
+ >
215
+ <p className="text-sm leading-6 text-muted-foreground">
216
+ {t("settings.chatFirstSessionWatchDescription")}
217
+ </p>
218
+ {chatFirstStorageAlert}
219
+ </SettingsRow>
220
+ </SettingsGroup>
221
+ </div>
222
+ }
223
+ generalGroups={
224
+ <SettingsGroup id="workspace" title={t("settings.workspaceTitle")}>
225
+ <SettingsRow
226
+ id="chat-first"
227
+ label={t("settings.chatFirstTitle")}
228
+ description={t("settings.chatFirstDescription")}
229
+ control={chatFirstSwitch}
230
+ >
231
+ {chatFirstStorageAlert}
232
+ </SettingsRow>
233
+ <SettingsRow
234
+ id="workspace-resources"
235
+ label={t("settings.resourcesTitle")}
236
+ description={t("settings.workspaceDescription")}
237
+ control={resourceSettingsButton}
238
+ />
239
+ {connectAppsRow}
240
+ </SettingsGroup>
241
+ }
242
+ whatsNew={
243
+ <div className="mx-auto w-full max-w-2xl">
244
+ <ChangelogSettingsCard markdown={changelog} />
245
+ </div>
246
+ }
247
+ whatsNewMarkdown={changelog}
248
+ />
249
+ );
250
+ }
@@ -1,257 +1,9 @@
1
- import {
2
- CHAT_FIRST_MODE_CHANGED_EVENT,
3
- readChatFirstModeState,
4
- writeChatFirstMode,
5
- } from "@agent-native/core/client/agent-chat";
6
- import {
7
- useFeatureFlag,
8
- useFeatureFlagState,
9
- } from "@agent-native/core/client/feature-flags";
10
- import { useT } from "@agent-native/core/client/i18n";
11
- import { SETTINGS_REDESIGN_FLAG } from "@agent-native/core/feature-flags/registry";
12
- import { ChangelogSettingsCard } from "@agent-native/toolkit/app/changelog";
13
- import { OrgMembersPage, TeamPage } from "@agent-native/toolkit/app/org";
14
- import {
15
- AccountSettingsCard,
16
- CORE_SETTINGS_PAGES,
17
- registerSettingsPages,
18
- SettingsGroup,
19
- SettingsRow,
20
- SettingsTabsPage,
21
- useAgentSettingsTabs,
22
- type SettingsSearchEntry,
23
- } from "@agent-native/toolkit/app/settings";
24
- import { LanguagePicker } from "@agent-native/toolkit/app/shared";
25
- import { IconShield } from "@tabler/icons-react";
26
- import { useMemo, useState } from "react";
27
- import { Link } from "react-router";
28
-
29
1
  import packageChangelog from "../../../CHANGELOG.md?raw";
30
- import { Button } from "../../components/ui/button";
31
- import { Switch } from "../../components/ui/switch";
32
- import { dispatchAccessDescriptor } from "../../shared/app-roles.js";
33
- import { DISPATCH_CONNECT_APPS_FLAG } from "../../shared/feature-flags.js";
34
-
35
- const coreMembersPage = CORE_SETTINGS_PAGES.find(
36
- (page) => page.id === "members",
37
- );
38
- if (!coreMembersPage) {
39
- throw new Error("Core Settings has no members page for Dispatch app roles");
40
- }
41
-
42
- function DispatchMembersSettingsPage() {
43
- return <OrgMembersPage appRoles={dispatchAccessDescriptor} />;
44
- }
2
+ import { DispatchSettingsPage } from "./settings-page.js";
45
3
 
46
- // The redesigned Settings shows Members from core; Dispatch's replaces it so
47
- // the app-role column stays.
48
- registerSettingsPages([
49
- { ...coreMembersPage, component: DispatchMembersSettingsPage },
50
- ]);
51
-
52
- export function meta() {
53
- return [{ title: "Settings - Dispatch" }];
54
- }
55
-
56
- export interface DispatchSettingsPageProps {
57
- /** Raw CHANGELOG.md behind What's new. */
58
- changelog: string;
59
- }
60
-
61
- /**
62
- * Dispatch's Settings. The template route renders it with the app's own
63
- * changelog; `dispatchRoutes` consumers get the default export.
64
- */
65
- export function DispatchSettingsPage({ changelog }: DispatchSettingsPageProps) {
66
- const t = useT();
67
- const connectAppsEnabled = useFeatureFlag(DISPATCH_CONNECT_APPS_FLAG.key);
68
- // Core Preferences owns the interface language in the redesigned Settings,
69
- // whose Dispatch General page shows `generalGroups` instead of `general`.
70
- const redesign = useFeatureFlagState(SETTINGS_REDESIGN_FLAG.key).enabled;
71
- const agentSettingsTabs = useAgentSettingsTabs({
72
- usageAppId: "dispatch",
73
- usageViewAllHref: "/admin/metrics",
74
- organizationContent: (
75
- <div className="mx-auto w-full max-w-3xl">
76
- <TeamPage
77
- showTitle={false}
78
- appRoles={dispatchAccessDescriptor}
79
- createOrgDescription="Set up a team to share dispatch destinations and approvals with your colleagues."
80
- />
81
- </div>
82
- ),
83
- });
84
- const settingsTabs = [
85
- ...agentSettingsTabs,
86
- {
87
- id: "admin",
88
- label: t("dispatch.nav.admin", { defaultValue: "Admin" }),
89
- icon: IconShield,
90
- group: "Admin",
91
- href: "/admin",
92
- content: null,
93
- },
94
- ];
95
- const [chatFirstModeState] = useState(() => readChatFirstModeState());
96
- const [chatFirstMode, setChatFirstMode] = useState(
97
- () => chatFirstModeState.enabled,
98
- );
99
- const [chatFirstStorageNotice, setChatFirstStorageNotice] = useState<
100
- string | null
101
- >(
102
- chatFirstModeState.availability === "unavailable"
103
- ? t("settings.chatFirstStorageUnavailable")
104
- : null,
105
- );
106
-
107
- function updateChatFirstMode(enabled: boolean) {
108
- const result = writeChatFirstMode(enabled);
109
- if (!result.ok) {
110
- setChatFirstStorageNotice(t("settings.chatFirstStorageBlocked"));
111
- return;
112
- }
113
- setChatFirstStorageNotice(null);
114
- setChatFirstMode(enabled);
115
- window.dispatchEvent(
116
- new CustomEvent(CHAT_FIRST_MODE_CHANGED_EVENT, {
117
- detail: { enabled },
118
- }),
119
- );
120
- }
121
-
122
- const generalSearchEntries = useMemo<SettingsSearchEntry[]>(
123
- () => [
124
- ...(redesign
125
- ? []
126
- : [
127
- {
128
- id: "dispatch-language",
129
- label: t("settings.languageTitle"),
130
- keywords: "language locale translation i18n",
131
- hash: "language",
132
- },
133
- ]),
134
- {
135
- id: "dispatch-workspace",
136
- label: redesign
137
- ? t("settings.resourcesTitle")
138
- : t("settings.workspaceTitle"),
139
- keywords: "workspace resources integrations vault destinations",
140
- hash: "workspace-resources",
141
- },
142
- {
143
- id: "dispatch-chat-first",
144
- label: t("settings.chatFirstTitle"),
145
- keywords: "chat first codex t3 apps pane navigation",
146
- hash: "chat-first",
147
- },
148
- ],
149
- [redesign, t],
150
- );
151
-
152
- const chatFirstSwitch = (
153
- <Switch
154
- aria-label={t("settings.chatFirstAriaLabel")}
155
- checked={chatFirstMode}
156
- onCheckedChange={updateChatFirstMode}
157
- />
158
- );
159
- const chatFirstStorageAlert = chatFirstStorageNotice ? (
160
- <p className="text-sm text-destructive" role="alert">
161
- {chatFirstStorageNotice}
162
- </p>
163
- ) : null;
164
- const connectAppsRow = connectAppsEnabled ? (
165
- <SettingsRow
166
- id="connect-apps"
167
- label={t("settings.connectApps")}
168
- description={t("settings.connectAppsDescription")}
169
- control={
170
- <Button variant="outline" asChild>
171
- <Link to="/connect">{t("settings.openConnectApps")}</Link>
172
- </Button>
173
- }
174
- />
175
- ) : null;
176
- const resourceSettingsButton = (
177
- <Button variant="outline" asChild>
178
- <Link to="/workspace">{t("settings.openResourceSettings")}</Link>
179
- </Button>
180
- );
181
-
182
- return (
183
- <SettingsTabsPage
184
- account={<AccountSettingsCard />}
185
- extraTabs={settingsTabs}
186
- generalSearchEntries={generalSearchEntries}
187
- general={
188
- <div className="mx-auto w-full max-w-2xl space-y-6">
189
- <p className="text-sm leading-6 text-muted-foreground">
190
- {t("settings.description")}
191
- </p>
192
-
193
- <SettingsGroup>
194
- <SettingsRow
195
- id="language"
196
- label={t("settings.languageTitle")}
197
- description={t("settings.languageDescription")}
198
- control={
199
- <div className="w-56">
200
- <LanguagePicker label={t("settings.languageLabel")} />
201
- </div>
202
- }
203
- />
204
- <SettingsRow
205
- id="workspace-resources"
206
- label={t("settings.workspaceTitle")}
207
- description={t("settings.workspaceDescription")}
208
- control={resourceSettingsButton}
209
- />
210
- {connectAppsRow}
211
- </SettingsGroup>
212
-
213
- <SettingsGroup id="chat-first">
214
- <SettingsRow
215
- label={t("settings.chatFirstTitle")}
216
- description={t("settings.chatFirstDescription")}
217
- control={chatFirstSwitch}
218
- >
219
- <p className="text-sm leading-6 text-muted-foreground">
220
- {t("settings.chatFirstSessionWatchDescription")}
221
- </p>
222
- {chatFirstStorageAlert}
223
- </SettingsRow>
224
- </SettingsGroup>
225
- </div>
226
- }
227
- generalGroups={
228
- <SettingsGroup id="workspace" title={t("settings.workspaceTitle")}>
229
- <SettingsRow
230
- id="chat-first"
231
- label={t("settings.chatFirstTitle")}
232
- description={t("settings.chatFirstDescription")}
233
- control={chatFirstSwitch}
234
- >
235
- {chatFirstStorageAlert}
236
- </SettingsRow>
237
- <SettingsRow
238
- id="workspace-resources"
239
- label={t("settings.resourcesTitle")}
240
- description={t("settings.workspaceDescription")}
241
- control={resourceSettingsButton}
242
- />
243
- {connectAppsRow}
244
- </SettingsGroup>
245
- }
246
- whatsNew={
247
- <div className="mx-auto w-full max-w-2xl">
248
- <ChangelogSettingsCard markdown={changelog} />
249
- </div>
250
- }
251
- whatsNewMarkdown={changelog}
252
- />
253
- );
254
- }
4
+ export { DispatchSettingsPage };
5
+ export type { DispatchSettingsPageProps } from "./settings-page.js";
6
+ export { meta } from "./settings-page.js";
255
7
 
256
8
  export default function SettingsRoute() {
257
9
  return <DispatchSettingsPage changelog={packageChangelog} />;