@agent-native/core 0.146.4 → 0.146.6

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.
Files changed (113) hide show
  1. package/corpus/templates/analytics/app/components/layout/CommandPalette.tsx +1 -1
  2. package/corpus/templates/analytics/app/components/layout/Layout.tsx +1 -1
  3. package/corpus/templates/analytics/app/pages/Settings.tsx +5 -1
  4. package/corpus/templates/analytics/app/routes/agent.tsx +7 -5
  5. package/corpus/templates/analytics/server/jobs/analytics-bigquery-backfill.ts +13 -9
  6. package/corpus/templates/analytics/server/lib/first-party-analytics-backend.ts +69 -33
  7. package/corpus/templates/assets/app/components/layout/Layout.tsx +1 -1
  8. package/corpus/templates/assets/app/routes/agent.tsx +7 -5
  9. package/corpus/templates/assets/app/routes/settings.tsx +7 -2
  10. package/corpus/templates/assets/server/plugins/creative-context.ts +1 -1
  11. package/corpus/templates/brain/app/components/layout/Layout.tsx +1 -1
  12. package/corpus/templates/brain/app/lib/brain.ts +4 -2
  13. package/corpus/templates/brain/app/root.tsx +1 -1
  14. package/corpus/templates/brain/app/routes/agent.tsx +10 -2
  15. package/corpus/templates/calendar/app/components/layout/AppLayout.tsx +1 -1
  16. package/corpus/templates/calendar/app/root.tsx +1 -2
  17. package/corpus/templates/calendar/app/routes/_app.agent.tsx +8 -16
  18. package/corpus/templates/chat/app/hooks/use-navigation-state.ts +5 -2
  19. package/corpus/templates/chat/app/routes/agent.tsx +7 -31
  20. package/corpus/templates/clips/app/components/library/library-layout.tsx +1 -1
  21. package/corpus/templates/clips/app/root.tsx +1 -2
  22. package/corpus/templates/clips/app/routes/_app.agent.tsx +9 -7
  23. package/corpus/templates/content/app/components/layout/Layout.tsx +1 -1
  24. package/corpus/templates/content/app/root.tsx +1 -2
  25. package/corpus/templates/content/app/routes/_app.agent.tsx +9 -8
  26. package/corpus/templates/content/app/routes/_app.settings.tsx +7 -2
  27. package/corpus/templates/content/server/plugins/creative-context.ts +1 -1
  28. package/corpus/templates/crm/app/components/crm/RecordActions.tsx +4 -1
  29. package/corpus/templates/crm/app/components/layout/CrmLayout.tsx +1 -1
  30. package/corpus/templates/crm/app/routes/agent.tsx +10 -2
  31. package/corpus/templates/design/app/components/layout/Layout.tsx +1 -1
  32. package/corpus/templates/design/app/root.tsx +1 -1
  33. package/corpus/templates/design/app/routes/agent.tsx +9 -7
  34. package/corpus/templates/design/app/routes/settings.tsx +7 -2
  35. package/corpus/templates/design/server/plugins/creative-context.ts +1 -1
  36. package/corpus/templates/dispatch/app/root.tsx +5 -2
  37. package/corpus/templates/dispatch/app/routes/agent.tsx +7 -7
  38. package/corpus/templates/factory/app/components/layout/Layout.tsx +1 -1
  39. package/corpus/templates/factory/app/hooks/use-navigation-state.ts +5 -2
  40. package/corpus/templates/factory/app/root.tsx +1 -1
  41. package/corpus/templates/factory/app/routes/agent.tsx +9 -14
  42. package/corpus/templates/forms/app/components/layout/Layout.tsx +1 -1
  43. package/corpus/templates/forms/app/root.tsx +1 -1
  44. package/corpus/templates/forms/app/routes/_app.agent.tsx +9 -7
  45. package/corpus/templates/macros/app/components/layout/AppLayout.tsx +5 -3
  46. package/corpus/templates/macros/app/root.tsx +1 -1
  47. package/corpus/templates/macros/app/routes/agent.tsx +9 -6
  48. package/corpus/templates/mail/app/components/layout/AppLayout.tsx +8 -2
  49. package/corpus/templates/mail/app/components/layout/CommandPalette.tsx +1 -1
  50. package/corpus/templates/mail/app/routes/agent.tsx +9 -6
  51. package/corpus/templates/plan/app/components/layout/Layout.tsx +1 -1
  52. package/corpus/templates/plan/app/root.tsx +1 -1
  53. package/corpus/templates/plan/app/routes/agent.tsx +9 -6
  54. package/corpus/templates/slides/app/components/editor/ImageGenPanel.tsx +8 -12
  55. package/corpus/templates/slides/app/components/editor/SlideEditor.tsx +39 -2
  56. package/corpus/templates/slides/app/components/layout/Layout.tsx +1 -1
  57. package/corpus/templates/slides/app/i18n/en-US.ts +1 -0
  58. package/corpus/templates/slides/app/lib/create-deck-generation.ts +22 -5
  59. package/corpus/templates/slides/app/pages/Index.tsx +20 -5
  60. package/corpus/templates/slides/app/root.tsx +1 -1
  61. package/corpus/templates/slides/app/routes/agent.tsx +6 -9
  62. package/corpus/templates/slides/app/routes/settings.tsx +7 -2
  63. package/corpus/templates/slides/server/plugins/creative-context.ts +1 -1
  64. package/corpus/templates/tasks/app/components/layout/Layout.tsx +1 -1
  65. package/corpus/templates/tasks/app/routes/agent.tsx +10 -2
  66. package/dist/client/index.d.ts +1 -1
  67. package/dist/client/navigation/index.d.ts +1 -1
  68. package/dist/client/navigation/index.js +1 -1
  69. package/dist/client/org/OrgSwitcher.js +1 -1
  70. package/dist/client/settings/SettingsPanel.d.ts +8 -0
  71. package/dist/client/settings/SettingsPanel.js +16 -1
  72. package/dist/client/settings/index.d.ts +1 -1
  73. package/dist/collab/awareness.d.ts +2 -2
  74. package/dist/collab/routes.d.ts +1 -1
  75. package/dist/deploy/build.d.ts +21 -0
  76. package/dist/deploy/build.js +185 -10
  77. package/dist/jobs/background-automation-runner.d.ts +1 -1
  78. package/dist/jobs/background-automation-runner.js +1 -1
  79. package/dist/jobs/scheduler-health.d.ts +4 -0
  80. package/dist/jobs/scheduler-health.js +33 -0
  81. package/dist/localization/server.d.ts +0 -1
  82. package/dist/localization/server.js +3 -1
  83. package/dist/mcp-client/index.d.ts +1 -1
  84. package/dist/mcp-client/index.js +1 -1
  85. package/dist/mcp-client/routes.d.ts +11 -0
  86. package/dist/mcp-client/routes.js +26 -1
  87. package/dist/navigation/index.d.ts +1 -0
  88. package/dist/navigation/index.js +34 -0
  89. package/dist/notifications/routes.d.ts +2 -2
  90. package/dist/observability/routes.d.ts +3 -3
  91. package/dist/provider-api/actions/custom-provider-registration.d.ts +6 -6
  92. package/dist/provider-api/actions/provider-api.d.ts +5 -5
  93. package/dist/provider-api/corpus-jobs.d.ts +2 -2
  94. package/dist/secrets/routes.d.ts +6 -6
  95. package/dist/server/agent-chat/mcp-glue.js +12 -3
  96. package/dist/server/agent-chat-plugin.js +73 -48
  97. package/dist/server/http-response-telemetry.js +112 -5
  98. package/dist/server/realtime-token.d.ts +1 -1
  99. package/dist/server/release-migrations.js +2 -0
  100. package/dist/server/ssr-handler.js +8 -0
  101. package/dist/server/transcribe-voice.d.ts +1 -1
  102. package/dist/templates/chat/app/hooks/use-navigation-state.ts +5 -2
  103. package/dist/templates/chat/app/routes/agent.tsx +7 -31
  104. package/dist/templates/default/app/routes/_index.tsx +1 -1
  105. package/dist/templates/default/app/routes/agent.tsx +7 -25
  106. package/dist/templates/workspace-core/.agents/skills/performance/SKILL.md +54 -3
  107. package/dist/vite/client.js +5 -1
  108. package/package.json +1 -1
  109. package/src/templates/chat/app/hooks/use-navigation-state.ts +5 -2
  110. package/src/templates/chat/app/routes/agent.tsx +7 -31
  111. package/src/templates/default/app/routes/_index.tsx +1 -1
  112. package/src/templates/default/app/routes/agent.tsx +7 -25
  113. package/src/templates/workspace-core/.agents/skills/performance/SKILL.md +54 -3
@@ -1,4 +1,8 @@
1
- import { callAction } from "@agent-native/core/client/hooks";
1
+ import {
2
+ callAction,
3
+ deleteClientAppState,
4
+ } from "@agent-native/core/client/hooks";
5
+ import { appStateKeyForBrowserTab } from "@shared/app-state-tabs";
2
6
  import { extractGoogleDocUrls } from "@shared/google-docs";
3
7
  import { flushSync } from "react-dom";
4
8
 
@@ -10,6 +14,7 @@ import {
10
14
  importUploadedDeckIntoDeck,
11
15
  type ImportedSourceDeck,
12
16
  } from "@/lib/import-uploaded-deck";
17
+ import { TAB_ID } from "@/lib/tab-id";
13
18
 
14
19
  interface DesignSystemGenerationContextResult {
15
20
  agentContext?: string;
@@ -103,7 +108,7 @@ function describeUploadedFilesForAgent(
103
108
  "",
104
109
  importedSourceDeck
105
110
  ? `The user uploaded ${files.length} file(s). The ${sourceFile?.originalName ?? importedSourceDeck.format.toUpperCase()} source deck has already been imported into target deck ${deckId} with ${importedSourceDeck.slideCount} source slide(s); do not import it again.`
106
- : `The user uploaded ${files.length} file(s). These paths are real uploaded files; process them with import actions before using their contents:`,
111
+ : `The user uploaded ${files.length} file(s). These are mandatory source material, not optional references — process every one of them with the matching import action BEFORE adding the first slide:`,
107
112
  fileList,
108
113
  "",
109
114
  "File handling rules:",
@@ -112,10 +117,11 @@ function describeUploadedFilesForAgent(
112
117
  : `- PPTX files: call \`import-pptx --filePath \"<path>\" --deckId ${deckId}\` before adding or editing slides.`,
113
118
  importedSourceDeck
114
119
  ? "- For a PDF source, keep the original full-page image in every slide and add restrained design-system chrome around it without obscuring source content. Never OCR-reconstruct a source-faithful page from extracted text."
115
- : `- PDF and DOCX files: call \`import-file --filePath \"<path>\" --format auto --deckId ${deckId}\` and use the returned extracted text as source material. For a visual PDF whose original layout should be preserved, pass \`--importIntoDeck true\` instead of rebuilding the pages from extracted text.`,
120
+ : `- PDF and DOCX files: call \`import-file --filePath \"<path>\" --format auto --deckId ${deckId}\` and use the returned extracted text as source material. The returned text is capped for reliability; re-run with maxChars only if more context is needed. For a visual PDF whose original layout should be preserved, pass \`--importIntoDeck true\` instead of rebuilding the pages from extracted text. Do not proceed to add-slide until this call has returned for every PDF/DOCX in the list above.`,
116
121
  "- Text-like files: use the uploaded-text-file blocks already included in the prompt; do not call import-file for them.",
117
- '- Image files with an embeddable URL can be inserted directly into slide HTML as `<img src="...">` or used as visual references.',
122
+ '- Image files with an embeddable URL are mandatory assets: if the user specified where to use one (e.g. "on the first and last slide"), embed it there with `<img src="...">` exactly as requested. Do not omit a requested image and continue silently — if it truly cannot be placed, say why in your final chat response.',
118
123
  "- Image files without a URL are visual/reference assets only; do not claim to have processed a PPTX/PDF/DOCX unless the relevant import action succeeds.",
124
+ "- Before your final response, verify every uploaded file above was either imported (PPTX/PDF/DOCX) or placed as requested (images). If any file's content or requested placement is missing from the deck, say so explicitly instead of reporting success.",
119
125
  ].join("\n");
120
126
  }
121
127
 
@@ -351,12 +357,23 @@ export async function startDeckGeneration({
351
357
  "",
352
358
  "Before generating, if the request or selected references leave a meaningful choice unresolved, use the `ask-question` tool to ask one concise, prompt-specific question in the inline guided-question flow. Generate the question wording and 2 to 4 options from the user's request and selected references, like Claude's design-question flow; do not use a fixed generic questionnaire. Ask only a choice that materially affects the deck, such as audience, tone, structure, or length. If the prompt already makes the choice clear, do not ask it again. Wait for the user's answer or skip before adding slides.",
353
359
  sourceModeInstructions,
354
- "If the user asked for a specific slide count, keep going sequentially until that count is reached unless a tool error blocks you.",
360
+ "If the user asked for a specific slide count, keep going sequentially until that count is reached unless a tool error blocks you. If no explicit count was given (including when the guided slide-count question was skipped), infer the count from the distinct topics/sections implied by the request — one slide per section plus a title and closing slide — and add slides for every section before considering the deck done. Do not stop at an arbitrary round number (e.g. 10) if sections remain uncovered, and never call `generate-slides-ai` for this flow; it is a legacy single-shot helper capped at 10 slides.",
355
361
  "Every slide is rendered into a fixed native canvas (default 16:9 is 960x540 CSS pixels, with 740x380px available inside standard 80px 110px padding). Keep the main content within that fit budget; split dense source material across more slides instead of packing it tightly. Never use zoom, transform: scale(), clipping, or scroll overflow to hide content overflow, and keep body text at least 16px.",
356
362
  "Each slide's --content must be full HTML. Slide HTML templates are in your AGENTS.md.",
357
363
  "Do NOT use create-deck (the deck already exists). Do NOT call db-schema, the resources tool, or search-files.",
358
364
  ].join("\n");
359
365
 
366
+ // A guided-question card from the previous deck's still-finishing agent run
367
+ // shares this browser tab's single "guided-questions" slot. Without
368
+ // clearing it here, a late answer to that stale question can render on top
369
+ // of the deck we're about to navigate to. Best-effort: if the previous
370
+ // run's question arrives after this clear, it can still reappear, but this
371
+ // closes the common case where it's already pending when a new deck starts.
372
+ deleteClientAppState(
373
+ appStateKeyForBrowserTab("guided-questions", TAB_ID),
374
+ ).catch(() => {});
375
+ deleteClientAppState("guided-questions").catch(() => {});
376
+
360
377
  navigate(`/deck/${deck.id}?generating=1`, {
361
378
  replace: true,
362
379
  flushSync: true,
@@ -1,10 +1,15 @@
1
- import { callAction, useSession } from "@agent-native/core/client/hooks";
1
+ import {
2
+ callAction,
3
+ deleteClientAppState,
4
+ useSession,
5
+ } from "@agent-native/core/client/hooks";
2
6
  import { useT } from "@agent-native/core/client/i18n";
3
7
  import { buildSignInReturnHref } from "@agent-native/core/client/ui";
4
8
  import {
5
9
  useSetHeaderActions,
6
10
  useSetPageTitle,
7
11
  } from "@agent-native/toolkit/app-shell";
12
+ import { appStateKeyForBrowserTab } from "@shared/app-state-tabs";
8
13
  import { extractGoogleDocUrls } from "@shared/google-docs";
9
14
  import {
10
15
  IconAlertTriangle,
@@ -61,6 +66,7 @@ import {
61
66
  rememberRecentReference,
62
67
  type RecentReference,
63
68
  } from "@/lib/recent-references";
69
+ import { TAB_ID } from "@/lib/tab-id";
64
70
 
65
71
  const NEW_DECK_DRAFT_SCOPE = "slides-new-deck";
66
72
  const PENDING_PROMPT_KEY = "slides:pending-deck-prompt";
@@ -198,7 +204,7 @@ function describeUploadedFilesForAgent(
198
204
  "",
199
205
  importedSourceDeck
200
206
  ? `The user uploaded ${files.length} file(s). The ${importedSourceDeck.file.originalName} source deck has already been imported into target deck ${deckId} with ${importedSourceDeck.slideCount} source slide(s); do not import it again.`
201
- : `The user uploaded ${files.length} file(s). These paths are real uploaded files; process them with import actions before using their contents:`,
207
+ : `The user uploaded ${files.length} file(s). These are mandatory source material, not optional references — process every one of them with the matching import action BEFORE adding the first slide:`,
202
208
  fileList,
203
209
  "",
204
210
  "File handling rules:",
@@ -207,10 +213,11 @@ function describeUploadedFilesForAgent(
207
213
  : `- PPTX files: call \`import-pptx --filePath "<path>" --deckId ${deckId}\` before adding or editing slides.`,
208
214
  importedSourceDeck
209
215
  ? "- For a PDF source, keep the original full-page image in every slide and add restrained design-system chrome around it without obscuring source content. Never OCR-reconstruct a source-faithful page from extracted text."
210
- : `- PDF and DOCX files: call \`import-file --filePath "<path>" --format auto --deckId ${deckId}\` and use the returned extracted text as source material. For a visual PDF whose original layout should be preserved, pass \`--importIntoDeck true\` instead of rebuilding the pages from extracted text.`,
216
+ : `- PDF and DOCX files: call \`import-file --filePath "<path>" --format auto --deckId ${deckId}\` and use the returned extracted text as source material. The returned text is capped for reliability; re-run with maxChars only if more context is needed. For a visual PDF whose original layout should be preserved, pass \`--importIntoDeck true\` instead of rebuilding the pages from extracted text. Do not proceed to add-slide until this call has returned for every PDF/DOCX in the list above.`,
211
217
  "- Text-like files: use the uploaded-text-file blocks already included in the prompt; do not call import-file for them.",
212
- '- Image files with an embeddable URL can be inserted directly into slide HTML as `<img src="...">` or used as visual references.',
218
+ '- Image files with an embeddable URL are mandatory assets: if the user specified where to use one (e.g. "on the first and last slide"), embed it there with `<img src="...">` exactly as requested. Do not omit a requested image and continue silently — if it truly cannot be placed, say why in your final chat response.',
213
219
  "- Image files without a URL are visual/reference assets only; do not claim to have processed a PPTX/PDF/DOCX unless the relevant import action succeeds.",
220
+ "- Before your final response, verify every uploaded file above was either imported (PPTX/PDF/DOCX) or placed as requested (images). If any file's content or requested placement is missing from the deck, say so explicitly instead of reporting success.",
214
221
  ].join("\n");
215
222
  }
216
223
 
@@ -731,12 +738,20 @@ export default function Index() {
731
738
  "",
732
739
  "Before generating, if the request or selected references leave a meaningful choice unresolved, use the `ask-question` tool to ask one concise, prompt-specific question in the inline guided-question flow. Generate the question wording and 2 to 4 options from the user's request and selected references, like Claude's design-question flow; do not use a fixed generic questionnaire. Ask only a choice that materially affects the deck, such as audience, tone, structure, or length. If the prompt already makes the choice clear, do not ask it again. Wait for the user's answer or skip before adding slides.",
733
740
  sourceModeInstructions,
734
- "If the user asked for a specific slide count, keep going sequentially until that count is reached unless a tool error blocks you.",
741
+ "If the user asked for a specific slide count, keep going sequentially until that count is reached unless a tool error blocks you. If no explicit count was given (including when the guided slide-count question was skipped), infer the count from the distinct topics/sections implied by the request — one slide per section plus a title and closing slide — and add slides for every section before considering the deck done. Do not stop at an arbitrary round number (e.g. 10) if sections remain uncovered, and never call `generate-slides-ai` for this flow; it is a legacy single-shot helper capped at 10 slides.",
735
742
  "Every slide is rendered into a fixed native canvas (default 16:9 is 960x540 CSS pixels, with 740x380px available inside standard 80px 110px padding). Keep the main content within that fit budget; split dense source material across more slides instead of packing it tightly. Never use zoom, transform: scale(), clipping, or scroll overflow to hide content overflow, and keep body text at least 16px.",
736
743
  "Each slide's --content must be full HTML. Slide HTML templates are in your AGENTS.md.",
737
744
  "Do NOT use create-deck (the deck already exists). Do NOT call db-schema, the resources tool, or search-files.",
738
745
  ].join("\n");
739
746
 
747
+ // See the matching comment in create-deck-generation.ts: clear any
748
+ // guided-question card left over from the previous deck's still-finishing
749
+ // run so it can't surface on top of the deck we're navigating to now.
750
+ deleteClientAppState(
751
+ appStateKeyForBrowserTab("guided-questions", TAB_ID),
752
+ ).catch(() => {});
753
+ deleteClientAppState("guided-questions").catch(() => {});
754
+
740
755
  navigate(`/deck/${deck.id}?generating=1`, {
741
756
  replace: true,
742
757
  flushSync: true,
@@ -229,7 +229,7 @@ function AppContent() {
229
229
  {t("root.searchDecks")}
230
230
  </CommandMenu.Item>
231
231
  <CommandMenu.Item
232
- onSelect={() => navigate("/agent")}
232
+ onSelect={() => navigate("/settings/agent")}
233
233
  keywords={["agent", "context", "connections", "jobs", "access"]}
234
234
  >
235
235
  <IconHierarchy2 size={16} />
@@ -1,7 +1,5 @@
1
- import { AgentTabsPage } from "@agent-native/core/client/agent-chat";
2
- import { useT } from "@agent-native/core/client/i18n";
3
- import { createCreativeContextAgentTab } from "@agent-native/creative-context/client";
4
- import { useSetPageTitle } from "@agent-native/toolkit/app-shell";
1
+ import { buildLegacyAgentSettingsRoute } from "@agent-native/core/client/navigation";
2
+ import { Navigate, useLocation } from "react-router";
5
3
 
6
4
  import messages from "@/i18n/en-US";
7
5
 
@@ -10,13 +8,12 @@ export function meta() {
10
8
  }
11
9
 
12
10
  export default function AgentRoute() {
13
- const t = useT();
14
- useSetPageTitle(t("settings.agentTitle"));
11
+ const location = useLocation();
15
12
 
16
13
  return (
17
- <AgentTabsPage
18
- appName="Slides"
19
- extraTabFactories={[createCreativeContextAgentTab]}
14
+ <Navigate
15
+ to={buildLegacyAgentSettingsRoute(location.hash, location.search)}
16
+ replace
20
17
  />
21
18
  );
22
19
  }
@@ -9,7 +9,10 @@ import {
9
9
  useAgentSettingsTabs,
10
10
  type SettingsSearchEntry,
11
11
  } from "@agent-native/core/client/settings";
12
- import { CreativeContextSettingsLink } from "@agent-native/creative-context/client";
12
+ import {
13
+ CreativeContextSettingsLink,
14
+ createCreativeContextAgentTab,
15
+ } from "@agent-native/creative-context/client";
13
16
  import { useSetPageTitle } from "@agent-native/toolkit/app-shell";
14
17
  import { useMemo } from "react";
15
18
  import { toast } from "sonner";
@@ -26,7 +29,9 @@ export function meta() {
26
29
 
27
30
  export default function SettingsRoute() {
28
31
  const t = useT();
29
- const agentSettingsTabs = useAgentSettingsTabs();
32
+ const agentSettingsTabs = useAgentSettingsTabs({
33
+ agentAdditionalTabFactories: [createCreativeContextAgentTab],
34
+ });
30
35
  useSetPageTitle(t("settings.title"));
31
36
  const { prefs, loading: prefsLoading, save: savePrefs } = useSlidesPrefs();
32
37
 
@@ -165,7 +165,7 @@ registerOnboardingStep({
165
165
  kind: "link",
166
166
  primary: true,
167
167
  label: "Open Library",
168
- payload: { url: "/agent#library", external: false },
168
+ payload: { url: "/settings/library", external: false },
169
169
  },
170
170
  ],
171
171
  isComplete: async () => {
@@ -113,7 +113,7 @@ export function Layout({ children }: LayoutProps) {
113
113
  chatViewTransition
114
114
  storageKey="tasks"
115
115
  browserTabId={TAB_ID}
116
- agentPageHref="/agent"
116
+ agentPageHref="/settings/agent"
117
117
  onFullscreenRequest={() => focusAgentChat()}
118
118
  emptyStateText={t("agent.emptyState")}
119
119
  dynamicSuggestions={false}
@@ -1,4 +1,5 @@
1
- import { AgentTabsPage } from "@agent-native/core/client/agent-chat";
1
+ import { buildLegacyAgentSettingsRoute } from "@agent-native/core/client/navigation";
2
+ import { Navigate, useLocation } from "react-router";
2
3
 
3
4
  import { APP_TITLE } from "@/lib/app-config";
4
5
 
@@ -7,5 +8,12 @@ export function meta() {
7
8
  }
8
9
 
9
10
  export default function AgentRoute() {
10
- return <AgentTabsPage appName={APP_TITLE} />;
11
+ const location = useLocation();
12
+
13
+ return (
14
+ <Navigate
15
+ to={buildLegacyAgentSettingsRoute(location.hash, location.search)}
16
+ replace
17
+ />
18
+ );
11
19
  }
@@ -13,7 +13,7 @@ export { AgentNativeI18nProvider, LanguagePicker, getLocaleInitScript, localeDir
13
13
  export { AgentNativeIcon } from "./components/icons/AgentNativeIcon.js";
14
14
  export { FeatureFlagsEditor, evaluatedFeatureFlagValues, featureFlagValue, useFeatureFlag, useFeatureFlags, type FeatureFlagActor, type FeatureFlagMetadata, type FeatureFlagRules, type SetFeatureFlagInput, } from "./feature-flags/index.js";
15
15
  export { withBuilderUtmTrackingParams } from "../shared/builder-link-tracking.js";
16
- export { SettingsPanel, SettingsTabsPage, SecretsSection, getAgentSettingsSearchTabs, openBuilderConnectPopup, useAgentSettingsTabs, useBuilderConnectFlow, useBuilderStatus, withBuilderConnectTrackingParams, type BuilderConnectFlow, type BuilderConnectFlowOptions, type BuilderConnectStartOptions, type BuilderStatus, type AgentSettingsSearchTab, type OpenBuilderConnectPopupOptions, type SecretsSectionProps, type SettingsPanelProps, type SettingsSearchEntry, type SettingsTabItem, type SettingsTabsPageProps, } from "./settings/index.js";
16
+ export { SettingsPanel, SettingsTabsPage, SecretsSection, getAgentSettingsSearchTabs, openBuilderConnectPopup, useAgentSettingsTabs, type AgentSettingsTabFactory, type AgentSettingsTabFactoryContext, useBuilderConnectFlow, useBuilderStatus, withBuilderConnectTrackingParams, type BuilderConnectFlow, type BuilderConnectFlowOptions, type BuilderConnectStartOptions, type BuilderStatus, type AgentSettingsSearchTab, type OpenBuilderConnectPopupOptions, type SecretsSectionProps, type SettingsPanelProps, type SettingsSearchEntry, type SettingsTabItem, type SettingsTabsPageProps, } from "./settings/index.js";
17
17
  export { DevDatabaseLink, type DevDatabaseLinkProps, } from "./db-admin/DevDatabaseLink.js";
18
18
  export { DbAdminPage } from "./db-admin/DbAdminPage.js";
19
19
  export { installRouteChunkRecovery, reloadForStaleChunk, recoverFromStaleChunkError, } from "./route-chunk-recovery.js";
@@ -1,5 +1,5 @@
1
1
  export { agentNativePath, appApiPath, appBasePath, appPath, } from "../api-path.js";
2
2
  export { useAgentRouteState, useSemanticNavigationState, type AgentRouteLocation, type SemanticNavigationCommandEnvelope, type UseAgentRouteStateOptions, type UseAgentRouteStateResult, type UseSemanticNavigationStateOptions, type UseSemanticNavigationStateResult, } from "../route-state.js";
3
3
  export { COMMAND_MENU_OPEN_EVENT, CommandMenu, openAgentSidebar, openAgentSettings, openCommandMenu, submitToAgent, useCommandMenuShortcut, type CommandMenuProps, type CommandMenuDoc, type CommandDocsGroupProps, type CommandGroupProps, type CommandItemProps, type CommandShortcutProps, } from "../CommandMenu.js";
4
- export { buildOpenRouteLink, buildOpenRoutePath, buildResourceRoute, buildSettingsRoute, buildStandardAppRoute, buildTeamRoute, createStandardOpenPathResolver, STANDARD_APP_ROUTES, STANDARD_SETTINGS_TABS, type BuildResourceRouteOptions, type BuildStandardAppRouteOptions, type NavigationLink, type NavigationTarget, type StandardAppRouteId, type StandardOpenPathResolverOptions, type StandardOpenPathRoute, type StandardSettingsTabId, } from "../../navigation/index.js";
4
+ export { buildOpenRouteLink, buildOpenRoutePath, buildLegacyAgentSettingsRoute, buildResourceRoute, buildSettingsRoute, buildStandardAppRoute, buildTeamRoute, createStandardOpenPathResolver, STANDARD_APP_ROUTES, STANDARD_SETTINGS_TABS, type BuildResourceRouteOptions, type BuildStandardAppRouteOptions, type NavigationLink, type NavigationTarget, type StandardAppRouteId, type StandardOpenPathResolverOptions, type StandardOpenPathRoute, type StandardSettingsTabId, } from "../../navigation/index.js";
5
5
  export { postNavigate, isInAgentEmbed, AGENT_NAVIGATE_MESSAGE_TYPE, type AgentNavigateMessage, } from "../embed.js";
@@ -1,5 +1,5 @@
1
1
  export { agentNativePath, appApiPath, appBasePath, appPath, } from "../api-path.js";
2
2
  export { useAgentRouteState, useSemanticNavigationState, } from "../route-state.js";
3
3
  export { COMMAND_MENU_OPEN_EVENT, CommandMenu, openAgentSidebar, openAgentSettings, openCommandMenu, submitToAgent, useCommandMenuShortcut, } from "../CommandMenu.js";
4
- export { buildOpenRouteLink, buildOpenRoutePath, buildResourceRoute, buildSettingsRoute, buildStandardAppRoute, buildTeamRoute, createStandardOpenPathResolver, STANDARD_APP_ROUTES, STANDARD_SETTINGS_TABS, } from "../../navigation/index.js";
4
+ export { buildOpenRouteLink, buildOpenRoutePath, buildLegacyAgentSettingsRoute, buildResourceRoute, buildSettingsRoute, buildStandardAppRoute, buildTeamRoute, createStandardOpenPathResolver, STANDARD_APP_ROUTES, STANDARD_SETTINGS_TABS, } from "../../navigation/index.js";
5
5
  export { postNavigate, isInAgentEmbed, AGENT_NAVIGATE_MESSAGE_TYPE, } from "../embed.js";
@@ -32,7 +32,7 @@ const SWITCHER_BUTTON_CLASS = "flex w-full items-center gap-2 rounded-md border-
32
32
  const COMPACT_SWITCHER_BUTTON_CLASS = "flex items-center justify-center rounded-md border-0 bg-accent/50 p-1.5 text-muted-foreground hover:bg-accent/70 hover:text-foreground focus:outline-none focus-visible:ring-2 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-60 cursor-pointer";
33
33
  const DEFAULT_ORGANIZATION_SETTINGS_PATH = "/settings/organization";
34
34
  const DEFAULT_PROFILE_PATH = "/settings/account";
35
- const DEFAULT_AGENT_PATH = "/agent";
35
+ const DEFAULT_AGENT_PATH = "/settings/agent";
36
36
  const APP_ICON_MAP = {
37
37
  Mail: IconMail,
38
38
  CalendarDays: IconCalendar,
@@ -26,7 +26,15 @@ export interface AgentSettingsTabsOptions {
26
26
  extensionTools?: boolean;
27
27
  /** Optional page-level settings to show in the Agent section. */
28
28
  agentAdditionalContent?: React.ReactNode;
29
+ /** Optional app-owned tabs that share the Agent settings scope. */
30
+ agentAdditionalTabFactories?: AgentSettingsTabFactory[];
29
31
  }
32
+ export interface AgentSettingsTabFactoryContext {
33
+ scope: "user";
34
+ canManageOrg?: boolean;
35
+ scopeControl: React.ReactNode;
36
+ }
37
+ export type AgentSettingsTabFactory = (context: AgentSettingsTabFactoryContext) => SettingsTabItem;
30
38
  export declare function areExtensionSettingsEnabled(options?: AgentSettingsTabsOptions): boolean;
31
39
  export declare function SettingsPanel(props: SettingsPanelProps): React.JSX.Element;
32
40
  export declare function ConnectionsSettingsContent({ settingsPanelProps, }: {
@@ -13,6 +13,7 @@ import { BuilderBMark } from "../builder-mark.js";
13
13
  import { Popover, PopoverContent, PopoverTrigger, } from "../components/ui/popover.js";
14
14
  import { Tooltip, TooltipContent, TooltipTrigger, } from "../components/ui/tooltip.js";
15
15
  import { useT } from "../i18n.js";
16
+ import { useOrg } from "../org/hooks.js";
16
17
  import { TeamPage } from "../org/TeamPage.js";
17
18
  import { BuilderConnectCard } from "../setup-connections/BuilderConnectCard.js";
18
19
  import { callAction } from "../use-action.js";
@@ -1073,8 +1074,11 @@ export function AgentSettingsContent({ className, sections = AGENT_SETTINGS_SECT
1073
1074
  }
1074
1075
  export function useAgentSettingsTabs(options = {}) {
1075
1076
  const { isDevMode, canToggle, setDevMode } = useDevMode();
1077
+ const { data: org } = useOrg();
1078
+ const canManageOrg = !org?.orgId || org.role === "owner" || org.role === "admin";
1076
1079
  const extensionToolsEnabled = areExtensionSettingsEnabled(options);
1077
1080
  const agentAdditionalContent = options.agentAdditionalContent;
1081
+ const agentAdditionalTabFactories = options.agentAdditionalTabFactories ?? [];
1078
1082
  const baseProps = useMemo(() => ({
1079
1083
  isDevMode,
1080
1084
  onToggleDevMode: () => {
@@ -1082,6 +1086,11 @@ export function useAgentSettingsTabs(options = {}) {
1082
1086
  },
1083
1087
  showDevToggle: canToggle,
1084
1088
  }), [canToggle, isDevMode, setDevMode]);
1089
+ const additionalTabs = useMemo(() => agentAdditionalTabFactories.map((factory) => factory({
1090
+ scope: "user",
1091
+ canManageOrg,
1092
+ scopeControl: null,
1093
+ })), [agentAdditionalTabFactories, canManageOrg]);
1085
1094
  return useMemo(() => {
1086
1095
  const searchTabs = getAgentSettingsSearchTabs();
1087
1096
  const searchTab = (id) => {
@@ -1247,6 +1256,12 @@ export function useAgentSettingsTabs(options = {}) {
1247
1256
  ],
1248
1257
  content: _jsx(AgentWorkspaceContent, { activeTab: "agents", overview: null }),
1249
1258
  },
1259
+ ...additionalTabs,
1250
1260
  ];
1251
- }, [agentAdditionalContent, baseProps, extensionToolsEnabled]);
1261
+ }, [
1262
+ agentAdditionalContent,
1263
+ additionalTabs,
1264
+ baseProps,
1265
+ extensionToolsEnabled,
1266
+ ]);
1252
1267
  }
@@ -1,4 +1,4 @@
1
- export { AgentSettingsContent, areExtensionSettingsEnabled, SettingsPanel, useAgentSettingsTabs, type AgentSettingsTabsOptions, type SettingsPanelProps, } from "./SettingsPanel.js";
1
+ export { AgentSettingsContent, areExtensionSettingsEnabled, SettingsPanel, useAgentSettingsTabs, type AgentSettingsTabFactory, type AgentSettingsTabFactoryContext, type AgentSettingsTabsOptions, type SettingsPanelProps, } from "./SettingsPanel.js";
2
2
  export { getAgentSettingsSearchTabs, type AgentSettingsSearchTab, } from "./agent-settings-search.js";
3
3
  export { SettingsTabsPage, type SettingsSearchEntry, type SettingsTabItem, type SettingsTabsPageProps, } from "./SettingsTabsPage.js";
4
4
  export { AccountSettingsCard, AccountSettingsForm, type AccountSettingsCardProps, type AccountSettingsFormProps, } from "./AccountSettingsCard.js";
@@ -62,11 +62,11 @@ export declare const postAwareness: import("h3").EventHandlerWithFetch<import("h
62
62
  error: string;
63
63
  states?: undefined;
64
64
  } | {
65
- error?: undefined;
66
65
  states: {
67
66
  clientId: number;
68
67
  state: string;
69
68
  }[];
69
+ error?: undefined;
70
70
  }>>;
71
71
  /**
72
72
  * GET /_agent-native/collab/:docId/users
@@ -77,9 +77,9 @@ export declare const getActiveUsers: import("h3").EventHandlerWithFetch<import("
77
77
  error: string;
78
78
  users?: undefined;
79
79
  } | {
80
- error?: undefined;
81
80
  users: {
82
81
  clientId: number;
83
82
  lastSeen: number;
84
83
  }[];
84
+ error?: undefined;
85
85
  }>>;
@@ -26,8 +26,8 @@ export declare const getCollabState: import("h3").EventHandlerWithFetch<import("
26
26
  * Body: { update: string (base64), requestSource?: string }
27
27
  */
28
28
  export declare const postCollabUpdate: import("h3").EventHandlerWithFetch<import("h3").EventHandlerRequest, Promise<{
29
- ok?: undefined;
30
29
  error: string;
30
+ ok?: undefined;
31
31
  } | {
32
32
  error?: undefined;
33
33
  ok: boolean;
@@ -74,6 +74,14 @@ export { copyDir };
74
74
  export declare function isServerlessNativePlatformPackage(packageName: string): boolean;
75
75
  type ServerlessFfmpegStaticArch = "arm64" | "x64";
76
76
  export declare function shouldBundleFfmpegStaticForServerless(hostPlatform?: NodeJS.Platform, hostArch?: NodeJS.Architecture, targetArch?: ServerlessFfmpegStaticArch | null): boolean;
77
+ /**
78
+ * Which dependency gives this app a path to the serverless browser runtime, or
79
+ * null when it has none. Resolution cannot answer this: findInstalledPackageRoot
80
+ * falls back to an ancestor + .pnpm store walk, so in a workspace every app
81
+ * "resolves" the sibling package that actually declares Chromium and ships its
82
+ * ~80MB into every emitted function.
83
+ */
84
+ export declare function findServerlessBrowserRuntimeConsumer(projectCwd?: string): string | null;
77
85
  export declare function findInstalledPackageRoot(packageName: string, nodeModulesRoots: string[], fromPackageDir?: string): string | null;
78
86
  export declare function copyInstalledBrowserRuntimePackages(serverDir: string | undefined, projectCwd?: string): number;
79
87
  export declare function findInstalledFfmpegStaticPackage(nodeModulesRoots: string[]): string | null;
@@ -238,6 +246,19 @@ export declare function writeSingleTemplateNetlifyRedirects(projectCwd: string):
238
246
  * though the server bundle never imports Electron at runtime.
239
247
  */
240
248
  export declare function sanitizeServerlessFunctionPackageManifest(functionDir: string | undefined): void;
249
+ /**
250
+ * Nitro's dependency tracer is not subject to the copy-time filters above, so
251
+ * it ships every prebuild of a multi-platform native package plus whatever the
252
+ * local dev server left in `data/`. Prune both from the function dir before it
253
+ * is cloned for the extra functions, since each clone is zipped and uploaded in
254
+ * full.
255
+ *
256
+ * Only prunes inside a directory that still holds a runnable prebuild under the
257
+ * `isServerlessNativePlatformPackage` naming (`@libsql`, `@resvg`). Packages
258
+ * that name prebuilds differently — `@img/sharp-linux-x64` has no gnu/musl
259
+ * suffix — read as entirely dead and must be left alone.
260
+ */
261
+ export declare function pruneServerlessFunctionDeadWeight(functionDir: string | undefined): number;
241
262
  /**
242
263
  * Build for any non-Cloudflare preset using Nitro's programmatic build API.
243
264
  * Handles netlify, vercel, deno_deploy, aws-lambda, and all other targets.