@agent-native/core 0.149.5 → 0.151.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (197) hide show
  1. package/corpus/README.md +1 -1
  2. package/corpus/templates/analytics/.agents/skills/delegate-to-agent/SKILL.md +28 -0
  3. package/corpus/templates/analytics/.agents/skills/frontend-design/SKILL.md +5 -0
  4. package/corpus/templates/analytics/app/hooks/use-navigation-state.ts +83 -45
  5. package/corpus/templates/analytics/changelog/2026-08-11-analytics-dashboards-keep-the-selected-tab-when-reopened.md +6 -0
  6. package/corpus/templates/assets/.agents/skills/delegate-to-agent/SKILL.md +28 -0
  7. package/corpus/templates/assets/.agents/skills/frontend-design/SKILL.md +5 -0
  8. package/corpus/templates/brain/.agents/skills/delegate-to-agent/SKILL.md +28 -0
  9. package/corpus/templates/brain/.agents/skills/frontend-design/SKILL.md +5 -0
  10. package/corpus/templates/calendar/.agents/skills/delegate-to-agent/SKILL.md +28 -0
  11. package/corpus/templates/calendar/.agents/skills/frontend-design/SKILL.md +5 -0
  12. package/corpus/templates/chat/.agents/skills/delegate-to-agent/SKILL.md +28 -0
  13. package/corpus/templates/chat/.agents/skills/frontend-design/SKILL.md +5 -0
  14. package/corpus/templates/clips/.agents/skills/delegate-to-agent/SKILL.md +28 -0
  15. package/corpus/templates/clips/.agents/skills/frontend-design/SKILL.md +5 -0
  16. package/corpus/templates/clips/changelog/2026-08-11-clips-recovers-from-transient-updates-and-avoids-macos-priva.md +6 -0
  17. package/corpus/templates/clips/desktop/src/app.tsx +32 -176
  18. package/corpus/templates/clips/desktop/src/lib/updater.ts +52 -37
  19. package/corpus/templates/clips/desktop/src/styles.css +1 -166
  20. package/corpus/templates/clips/desktop/src-tauri/Cargo.toml +2 -0
  21. package/corpus/templates/clips/desktop/src-tauri/Info.plist +4 -0
  22. package/corpus/templates/clips/desktop/src-tauri/src/eventkit.rs +28 -1
  23. package/corpus/templates/clips/desktop/src-tauri/src/lib.rs +2 -0
  24. package/corpus/templates/clips/desktop/src-tauri/src/native_speech.rs +48 -1
  25. package/corpus/templates/clips/desktop/src-tauri/src/permission_status.rs +3 -0
  26. package/corpus/templates/clips/desktop/src-tauri/src/whisper_speech.rs +5 -0
  27. package/corpus/templates/clips/server/plugins/auth.ts +3 -0
  28. package/corpus/templates/content/.agents/skills/delegate-to-agent/SKILL.md +28 -0
  29. package/corpus/templates/content/.agents/skills/frontend-design/SKILL.md +5 -0
  30. package/corpus/templates/content/actions/_document-discovery-query.ts +127 -0
  31. package/corpus/templates/content/actions/list-documents.ts +189 -198
  32. package/corpus/templates/content/actions/search-documents.ts +95 -24
  33. package/corpus/templates/content/app/components/editor/CommentsSidebar.tsx +2 -1
  34. package/corpus/templates/content/app/hooks/use-documents.ts +84 -6
  35. package/corpus/templates/content/shared/api.ts +10 -0
  36. package/corpus/templates/design/.agents/skills/delegate-to-agent/SKILL.md +28 -0
  37. package/corpus/templates/design/.agents/skills/frontend-design/SKILL.md +5 -0
  38. package/corpus/templates/design/app/pages/DesignSystemSetup.tsx +5 -1
  39. package/corpus/templates/design/changelog/2026-08-11-design-agent-prompts-copy-successfully-in-the-desktop-app.md +6 -0
  40. package/corpus/templates/dispatch/.agents/skills/delegate-to-agent/SKILL.md +28 -0
  41. package/corpus/templates/dispatch/.agents/skills/frontend-design/SKILL.md +5 -0
  42. package/corpus/templates/dispatch/app/global.css +2 -2
  43. package/corpus/templates/dispatch/changelog/2026-08-10-desktop-workspace-sign-in.md +6 -0
  44. package/corpus/templates/dispatch/changelog/2026-08-11-dispatch-no-longer-shows-the-generic-chat-starter-among-defa.md +6 -0
  45. package/corpus/templates/dispatch/changelog/2026-08-11-integrations-and-scheduled-work-open-as-first-class-electron-pages.md +6 -0
  46. package/corpus/templates/dispatch/changelog/2026-08-11-sidebar-text-is-slightly-easier-to-read-in-light-and-dark-mo.md +6 -0
  47. package/corpus/templates/dispatch/server/lib/identity-sso.ts +57 -31
  48. package/corpus/templates/dispatch/server/plugins/feature-flags.ts +5 -0
  49. package/corpus/templates/dispatch/server/plugins/identity-sso.ts +82 -33
  50. package/corpus/templates/dispatch/server/plugins/org-apps-directory.ts +7 -15
  51. package/corpus/templates/dispatch/server/plugins/setup-dispatch.ts +9 -1
  52. package/corpus/templates/dispatch/shared/feature-flags.ts +15 -0
  53. package/corpus/templates/factory/.agents/skills/delegate-to-agent/SKILL.md +28 -0
  54. package/corpus/templates/factory/.agents/skills/frontend-design/SKILL.md +5 -0
  55. package/corpus/templates/forms/.agents/skills/delegate-to-agent/SKILL.md +28 -0
  56. package/corpus/templates/forms/.agents/skills/form-responses/SKILL.md +8 -7
  57. package/corpus/templates/forms/.agents/skills/frontend-design/SKILL.md +5 -0
  58. package/corpus/templates/forms/app/hooks/use-forms.ts +8 -1
  59. package/corpus/templates/forms/changelog/2026-08-11-fixed-public-forms-so-conditional-questions-stay-hidden-unti.md +6 -0
  60. package/corpus/templates/forms/server/handlers/submissions.ts +2 -1
  61. package/corpus/templates/forms/server/lib/public-form-ssr.ts +37 -2
  62. package/corpus/templates/forms/shared/page-url.ts +54 -0
  63. package/corpus/templates/forms/shared/types.ts +4 -4
  64. package/corpus/templates/macros/.agents/skills/frontend-design/SKILL.md +5 -0
  65. package/corpus/templates/mail/.agents/skills/delegate-to-agent/SKILL.md +28 -0
  66. package/corpus/templates/mail/.agents/skills/frontend-design/SKILL.md +5 -0
  67. package/corpus/templates/plan/.agents/skills/delegate-to-agent/SKILL.md +28 -0
  68. package/corpus/templates/plan/.agents/skills/frontend-design/SKILL.md +5 -0
  69. package/corpus/templates/slides/.agents/skills/delegate-to-agent/SKILL.md +28 -0
  70. package/corpus/templates/slides/.agents/skills/frontend-design/SKILL.md +5 -0
  71. package/corpus/templates/slides/actions/add-slide.ts +0 -27
  72. package/corpus/templates/slides/actions/import-file.ts +28 -9
  73. package/corpus/templates/slides/actions/view-screen.ts +4 -4
  74. package/corpus/templates/slides/app/components/design-system/DesignSystemSetup.tsx +8 -1
  75. package/corpus/templates/slides/app/components/editor/AiEditingMarker.tsx +25 -0
  76. package/corpus/templates/slides/app/components/editor/EditorSidebar.tsx +43 -48
  77. package/corpus/templates/slides/app/components/editor/EditorToolbar.tsx +9 -6
  78. package/corpus/templates/slides/app/components/editor/GeneratingSlidePreview.tsx +1 -9
  79. package/corpus/templates/slides/app/components/editor/ImageDropPromptPopover.tsx +2 -0
  80. package/corpus/templates/slides/app/components/editor/ImageOverlay.tsx +0 -26
  81. package/corpus/templates/slides/app/components/editor/SlideEditor.tsx +904 -217
  82. package/corpus/templates/slides/app/components/editor/canvas-interactions/index.ts +1 -0
  83. package/corpus/templates/slides/app/components/editor/canvas-interactions/slides-canvas-adapter.ts +11 -0
  84. package/corpus/templates/slides/app/components/editor/inline-edit-session.ts +16 -0
  85. package/corpus/templates/slides/app/components/editor/slide-object-interactions.ts +22 -6
  86. package/corpus/templates/slides/app/components/editor/style-clipboard.ts +61 -0
  87. package/corpus/templates/slides/app/components/layout/Layout.tsx +26 -2
  88. package/corpus/templates/slides/app/components/ui/context-menu.tsx +1 -0
  89. package/corpus/templates/slides/app/context/DeckContext.tsx +75 -25
  90. package/corpus/templates/slides/app/global.css +1 -1
  91. package/corpus/templates/slides/app/i18n/en-US.ts +6 -1
  92. package/corpus/templates/slides/app/lib/create-deck-generation.ts +1 -1
  93. package/corpus/templates/slides/app/lib/image-drop-to-agent.ts +12 -12
  94. package/corpus/templates/slides/app/lib/slide-agent-context.ts +52 -0
  95. package/corpus/templates/slides/app/lib/slide-image-replacement.ts +61 -0
  96. package/corpus/templates/slides/app/pages/DeckEditor.tsx +55 -116
  97. package/corpus/templates/slides/app/pages/Index.tsx +28 -3
  98. package/corpus/templates/slides/changelog/2026-08-11-agent-chat-now-follows-the-current-slide-and-selection.md +6 -0
  99. package/corpus/templates/slides/changelog/2026-08-11-deck-titles-now-use-slide-content-instead-of-placeholder-filenames.md +6 -0
  100. package/corpus/templates/slides/changelog/2026-08-11-history-now-opens-from-the-deck-overflow-menu.md +6 -0
  101. package/corpus/templates/slides/changelog/2026-08-11-images-can-be-dropped-directly-onto-slides-and-resized-or-re.md +6 -0
  102. package/corpus/templates/slides/changelog/2026-08-11-new-decks-now-transition-directly-to-a-full-page-editor-load.md +6 -0
  103. package/corpus/templates/slides/changelog/2026-08-11-selected-slide-layers-can-be-nudged-precisely-with-arrow-key.md +6 -0
  104. package/corpus/templates/slides/changelog/2026-08-11-slides-can-copy-and-paste-element-styles-with-cmd-option-c-v.md +6 -0
  105. package/corpus/templates/slides/changelog/2026-08-11-slides-shows-one-compact-ai-marker-and-keeps-your-current-sl.md +6 -0
  106. package/corpus/templates/slides/changelog/2026-08-11-text-edits-preserve-slide-layout-when-no-changes-are-made.md +6 -0
  107. package/corpus/templates/slides/changelog/2026-08-11-the-style-toolbar-now-uses-the-full-available-width.md +6 -0
  108. package/corpus/templates/slides/changelog/2026-08-11-undo-and-redo-now-move-one-visible-slide-state-at-a-time.md +6 -0
  109. package/corpus/templates/slides/server/lib/chat-attachments.ts +6 -2
  110. package/corpus/templates/slides/shared/deck-title.ts +56 -0
  111. package/corpus/templates/tasks/.agents/skills/delegate-to-agent/SKILL.md +28 -0
  112. package/corpus/templates/tasks/.agents/skills/frontend-design/SKILL.md +5 -0
  113. package/dist/agent/run-store.js +6 -1
  114. package/dist/agent/thread-data-builder.js +19 -44
  115. package/dist/agent/types.d.ts +13 -0
  116. package/dist/catalog.json +1 -0
  117. package/dist/cli/create.js +1 -1
  118. package/dist/client/AssistantChat.js +58 -10
  119. package/dist/client/FileStorageSetupCard.d.ts +6 -0
  120. package/dist/client/FileStorageSetupCard.js +18 -0
  121. package/dist/client/NewWorkspaceAppFlow.js +10 -0
  122. package/dist/client/agent-chat-adapter.js +87 -11
  123. package/dist/client/agent-chat.d.ts +1 -1
  124. package/dist/client/agent-chat.js +8 -3
  125. package/dist/client/chat/attachment-adapters.js +10 -0
  126. package/dist/client/chat/message-components.d.ts +4 -1
  127. package/dist/client/chat/message-components.js +37 -13
  128. package/dist/client/chat/tool-call-display.js +14 -0
  129. package/dist/client/chat-first/apps-rail.d.ts +1 -1
  130. package/dist/client/chat-first/apps-rail.js +6 -6
  131. package/dist/client/chat-first/copy.js +1 -0
  132. package/dist/client/chat-first/types.d.ts +1 -0
  133. package/dist/client/extensions/EmbeddedExtension.js +1 -1
  134. package/dist/client/extensions/ExtensionViewer.js +1 -1
  135. package/dist/client/extensions/InlineExtensionFrame.js +1 -1
  136. package/dist/client/onboarding/FirstRunOnboarding.js +17 -2
  137. package/dist/client/settings/FileStorageSettingsForm.d.ts +2 -0
  138. package/dist/client/settings/FileStorageSettingsForm.js +113 -0
  139. package/dist/client/settings/SettingsPanel.js +2 -1
  140. package/dist/client/sse-event-processor.js +21 -0
  141. package/dist/extensions/actions.js +2 -2
  142. package/dist/extensions/html-shell.js +3 -1
  143. package/dist/file-upload/pre-upload-attachments.d.ts +15 -10
  144. package/dist/file-upload/pre-upload-attachments.js +68 -24
  145. package/dist/file-upload/registry.d.ts +4 -5
  146. package/dist/file-upload/registry.js +7 -14
  147. package/dist/file-upload/s3.d.ts +9 -0
  148. package/dist/file-upload/s3.js +168 -0
  149. package/dist/file-upload/types.d.ts +3 -3
  150. package/dist/file-upload/types.js +2 -2
  151. package/dist/onboarding/app-profile.js +23 -1
  152. package/dist/onboarding/default-steps.js +69 -0
  153. package/dist/onboarding/types.d.ts +2 -0
  154. package/dist/progress/routes.d.ts +1 -1
  155. package/dist/provider-api/actions/custom-provider-registration.d.ts +11 -11
  156. package/dist/provider-api/actions/provider-api.d.ts +8 -8
  157. package/dist/resources/handlers.d.ts +1 -1
  158. package/dist/secrets/routes.d.ts +6 -6
  159. package/dist/server/agent-chat/browser-team-tools.js +20 -0
  160. package/dist/server/agent-chat-plugin.js +12 -3
  161. package/dist/server/auth.js +45 -21
  162. package/dist/server/better-auth-instance.d.ts +2 -0
  163. package/dist/server/better-auth-instance.js +2 -2
  164. package/dist/server/core-routes-plugin.d.ts +1 -0
  165. package/dist/server/core-routes-plugin.js +26 -16
  166. package/dist/server/identity-sso-store.d.ts +3 -0
  167. package/dist/server/identity-sso-store.js +45 -0
  168. package/dist/server/identity-sso.d.ts +20 -10
  169. package/dist/server/identity-sso.js +79 -31
  170. package/dist/server/index.d.ts +1 -1
  171. package/dist/server/index.js +1 -1
  172. package/dist/templates/chat/.agents/skills/delegate-to-agent/SKILL.md +28 -0
  173. package/dist/templates/chat/.agents/skills/frontend-design/SKILL.md +5 -0
  174. package/dist/templates/default/.agents/skills/delegate-to-agent/SKILL.md +28 -0
  175. package/dist/templates/default/.agents/skills/frontend-design/SKILL.md +5 -0
  176. package/dist/templates/workspace-core/.agents/skills/authentication/SKILL.md +24 -1
  177. package/dist/templates/workspace-core/.agents/skills/delegate-to-agent/SKILL.md +28 -0
  178. package/dist/templates/workspace-core/.agents/skills/extensions/SKILL.md +6 -2
  179. package/dist/templates/workspace-core/.agents/skills/extensions/references/api.md +1 -1
  180. package/dist/templates/workspace-core/.agents/skills/frontend-design/SKILL.md +5 -0
  181. package/dist/templates/workspace-core/.agents/skills/generative-ui/SKILL.md +3 -1
  182. package/docs/content/authentication.mdx +27 -0
  183. package/docs/content/cross-app-sso.mdx +38 -8
  184. package/docs/content/extensions.mdx +15 -15
  185. package/docs/content/file-uploads.mdx +10 -12
  186. package/docs/content/generative-ui.mdx +6 -1
  187. package/package.json +2 -2
  188. package/src/templates/chat/.agents/skills/delegate-to-agent/SKILL.md +28 -0
  189. package/src/templates/chat/.agents/skills/frontend-design/SKILL.md +5 -0
  190. package/src/templates/default/.agents/skills/delegate-to-agent/SKILL.md +28 -0
  191. package/src/templates/default/.agents/skills/frontend-design/SKILL.md +5 -0
  192. package/src/templates/workspace-core/.agents/skills/authentication/SKILL.md +24 -1
  193. package/src/templates/workspace-core/.agents/skills/delegate-to-agent/SKILL.md +28 -0
  194. package/src/templates/workspace-core/.agents/skills/extensions/SKILL.md +6 -2
  195. package/src/templates/workspace-core/.agents/skills/extensions/references/api.md +1 -1
  196. package/src/templates/workspace-core/.agents/skills/frontend-design/SKILL.md +5 -0
  197. package/src/templates/workspace-core/.agents/skills/generative-ui/SKILL.md +3 -1
@@ -15,6 +15,6 @@ export declare function createProgressHandler(): import("h3").EventHandlerWithFe
15
15
  error: string;
16
16
  ok?: undefined;
17
17
  } | {
18
- ok: boolean;
19
18
  error?: undefined;
19
+ ok: boolean;
20
20
  }>>;
@@ -77,7 +77,7 @@ export declare function createCustomProviderRegistrationAction<TSchema extends Z
77
77
  }, z.core.$strip>>, {
78
78
  id?: undefined;
79
79
  deleted?: undefined;
80
- provider?: undefined;
80
+ message?: undefined;
81
81
  providers: {
82
82
  id: string;
83
83
  label: string;
@@ -88,45 +88,45 @@ export declare function createCustomProviderRegistrationAction<TSchema extends Z
88
88
  updatedAt: number;
89
89
  }[];
90
90
  count: number;
91
+ provider?: undefined;
91
92
  found?: undefined;
92
93
  registered?: undefined;
93
94
  label?: undefined;
94
- message?: undefined;
95
95
  } | {
96
+ count?: undefined;
96
97
  id?: undefined;
97
98
  deleted?: undefined;
98
- count?: undefined;
99
+ message?: undefined;
99
100
  providers?: undefined;
100
101
  found: boolean;
101
102
  provider: import("../custom-registry.js").CustomProviderConfig;
102
103
  registered?: undefined;
103
104
  label?: undefined;
104
- message?: undefined;
105
105
  } | {
106
- deleted?: undefined;
107
106
  count?: undefined;
108
- provider?: undefined;
107
+ deleted?: undefined;
108
+ message?: undefined;
109
109
  providers?: undefined;
110
+ provider?: undefined;
110
111
  found: boolean;
111
112
  id: string;
112
113
  registered?: undefined;
113
114
  label?: undefined;
114
- message?: undefined;
115
115
  } | {
116
116
  count?: undefined;
117
- provider?: undefined;
117
+ message?: undefined;
118
118
  providers?: undefined;
119
+ provider?: undefined;
119
120
  found?: undefined;
120
121
  deleted: boolean;
121
122
  id: string;
122
123
  registered?: undefined;
123
124
  label?: undefined;
124
- message?: undefined;
125
125
  } | {
126
- deleted?: undefined;
127
126
  count?: undefined;
128
- provider?: undefined;
127
+ deleted?: undefined;
129
128
  providers?: undefined;
129
+ provider?: undefined;
130
130
  found?: undefined;
131
131
  registered: boolean;
132
132
  id: string;
@@ -311,8 +311,8 @@ export declare function createProviderApiActions(runtime: Pick<ProviderApiRuntim
311
311
  notes?: string | undefined;
312
312
  scope?: "org" | "user" | undefined;
313
313
  }, {
314
- message?: undefined;
315
314
  id?: undefined;
315
+ provider?: undefined;
316
316
  deleted?: undefined;
317
317
  providers: {
318
318
  id: string;
@@ -324,12 +324,11 @@ export declare function createProviderApiActions(runtime: Pick<ProviderApiRuntim
324
324
  updatedAt: number;
325
325
  }[];
326
326
  count: number;
327
- provider?: undefined;
328
327
  found?: undefined;
329
328
  registered?: undefined;
330
329
  label?: undefined;
331
- } | {
332
330
  message?: undefined;
331
+ } | {
333
332
  count?: undefined;
334
333
  id?: undefined;
335
334
  deleted?: undefined;
@@ -338,31 +337,32 @@ export declare function createProviderApiActions(runtime: Pick<ProviderApiRuntim
338
337
  provider: import("../custom-registry.js").CustomProviderConfig;
339
338
  registered?: undefined;
340
339
  label?: undefined;
341
- } | {
342
340
  message?: undefined;
341
+ } | {
343
342
  count?: undefined;
343
+ provider?: undefined;
344
344
  deleted?: undefined;
345
345
  providers?: undefined;
346
- provider?: undefined;
347
346
  found: boolean;
348
347
  id: string;
349
348
  registered?: undefined;
350
349
  label?: undefined;
351
- } | {
352
350
  message?: undefined;
351
+ } | {
353
352
  count?: undefined;
354
- providers?: undefined;
355
353
  provider?: undefined;
354
+ providers?: undefined;
356
355
  found?: undefined;
357
356
  deleted: boolean;
358
357
  id: string;
359
358
  registered?: undefined;
360
359
  label?: undefined;
360
+ message?: undefined;
361
361
  } | {
362
362
  count?: undefined;
363
+ provider?: undefined;
363
364
  deleted?: undefined;
364
365
  providers?: undefined;
365
- provider?: undefined;
366
366
  found?: undefined;
367
367
  registered: boolean;
368
368
  id: string;
@@ -48,8 +48,8 @@ export declare function handleUpdateResource(event: any): Promise<import("./stor
48
48
  }>;
49
49
  /** DELETE /_agent-native/resources/:id — delete a resource */
50
50
  export declare function handleDeleteResource(event: any): Promise<{
51
- error: string;
52
51
  ok?: undefined;
52
+ error: string;
53
53
  } | {
54
54
  error?: undefined;
55
55
  ok: boolean;
@@ -37,17 +37,17 @@ export declare function createWriteSecretHandler(): import("h3").EventHandlerWit
37
37
  ok?: undefined;
38
38
  status?: undefined;
39
39
  } | {
40
- error?: undefined;
41
40
  ok: boolean;
42
41
  status: string;
42
+ error?: undefined;
43
43
  } | {
44
44
  ok?: undefined;
45
45
  error: string;
46
46
  removed?: undefined;
47
47
  } | {
48
- error?: undefined;
49
48
  ok: boolean;
50
49
  removed: boolean;
50
+ error?: undefined;
51
51
  }>>;
52
52
  /**
53
53
  * POST /_agent-native/secrets/:key/test — validate an optional candidate value
@@ -58,13 +58,13 @@ export declare function createTestSecretHandler(): import("h3").EventHandlerWith
58
58
  error: string;
59
59
  note?: undefined;
60
60
  } | {
61
- error?: undefined;
62
61
  ok: boolean;
63
62
  note?: undefined;
64
- } | {
65
63
  error?: undefined;
64
+ } | {
66
65
  ok: boolean;
67
66
  note: string;
67
+ error?: undefined;
68
68
  } | {
69
69
  note?: undefined;
70
70
  ok: boolean;
@@ -95,11 +95,11 @@ export interface AdHocSecretPayload {
95
95
  export declare function createAdHocSecretHandler(): import("h3").EventHandlerWithFetch<import("h3").EventHandlerRequest, Promise<AdHocSecretPayload[] | {
96
96
  error: string;
97
97
  } | {
98
- error?: undefined;
99
98
  ok: boolean;
100
99
  key: string;
101
- } | {
102
100
  error?: undefined;
101
+ } | {
103
102
  ok: boolean;
104
103
  removed: boolean;
104
+ error?: undefined;
105
105
  }>>;
@@ -1,4 +1,5 @@
1
1
  import { createHash } from "node:crypto";
2
+ import { getActiveFileUploadProviderForRequest } from "../../file-upload/registry.js";
2
3
  import { areBuiltinMcpCapabilitiesSupported, buildMergedConfig, setBuiltinMcpCapabilityEnabled, } from "../../mcp-client/index.js";
3
4
  import { getBuilderBrowserConnectUrlForOwner, resolveBuilderBranchProjectId, } from "../builder-browser.js";
4
5
  import { getRequestUserEmail } from "../request-context.js";
@@ -73,6 +74,25 @@ export function createBuilderBrowserTool(deps) {
73
74
  return { ok: true, enabledIds: enabledIds ?? [] };
74
75
  };
75
76
  const entries = {
77
+ "connect-file-storage": {
78
+ tool: {
79
+ description: "Render the inline file-storage setup card when an image or file attachment could not be durably uploaded. The card lets the user connect Builder for managed object storage or open the same custom-key setup used by onboarding. Call it immediately when the attachment context says storage is missing; do not ask the user to upload the file again.",
80
+ parameters: {
81
+ type: "object",
82
+ properties: {},
83
+ },
84
+ },
85
+ run: async () => {
86
+ const activeProvider = await getActiveFileUploadProviderForRequest();
87
+ const ownerEmail = deps.getOwner?.() ?? getRequestUserEmail();
88
+ return JSON.stringify({
89
+ kind: "connect-file-storage-card",
90
+ configured: !!activeProvider,
91
+ provider: activeProvider?.name ?? null,
92
+ connectUrl: getBuilderBrowserConnectUrlForOwner(deps.getOrigin(), ownerEmail),
93
+ });
94
+ },
95
+ },
76
96
  "connect-builder": {
77
97
  tool: {
78
98
  description: `Render a Builder.io card inline in the chat. Call this as the first step (no code exploration or planning needed) when the user asks to modify the APP'S OWN SOURCE CODE: add a feature, change the UI chrome, edit a React component, add a route, add an integration, fix a bug in the app itself, or anything else that requires source-file edits while in hosted/production mode. ${extensionRequestGuidance}Do NOT call this for content the app is meant to produce — creating a video, generating a design, drafting an email, building a slide deck, making a dashboard, etc. — those run through the app's own domain actions, not Builder. Do NOT mention 'click Send to Builder' in your response unless this card is already in the conversation. The tool result includes \`builderEnabled\`; treat \`true\` as "Builder Cloud Agents can take the code-change handoff" and \`false\` as "this still needs a code change, but no Builder Cloud Agent can run here." If Builder is connected and Builder Cloud Agents are available, the card shows a 'Send to Builder' button that hands the work off to Builder's cloud agent and returns a branch URL. If \`builderEnabled\` is false, the card still renders but shows the code-change fallback: "This requires a code change. Edit locally or use Builder.io to edit this code in the cloud and continue customizing the app any way you like." Never tell the user to enable Builder Cloud Agents in Builder org settings or beta settings, and do not claim the Builder card has everything, is pre-loaded for handoff, or can run the cloud agent when \`builderEnabled\` is false. When you call this for a code-change request, pass the user's request verbatim as the \`prompt\` arg so the card can forward it to Builder unchanged when cloud agents are available.`,
@@ -951,9 +951,18 @@ export function createAgentChatPlugin(options) {
951
951
  const corpusToolNames = loadCorpusToolsInitially
952
952
  ? corpusToolNamesTaughtByPrompt(corpusPromptRegistry)
953
953
  : [];
954
- const effectiveInitialToolNames = corpusToolNames.length > 0
955
- ? [...new Set([...templateInitialToolNames, ...corpusToolNames])]
956
- : templateInitialToolNames;
954
+ const effectiveInitialToolNames = [
955
+ ...new Set([
956
+ ...templateInitialToolNames,
957
+ ...corpusToolNames,
958
+ // Attachment setup is a recovery action, but it must be available on
959
+ // the first request so a missing provider renders the CTA immediately
960
+ // instead of spending another turn in tool-search.
961
+ ...(browserTools["connect-file-storage"]
962
+ ? ["connect-file-storage"]
963
+ : []),
964
+ ]),
965
+ ];
957
966
  const resolveExtraContext = async (event, owner) => {
958
967
  if (!options?.extraContext)
959
968
  return "";
@@ -55,6 +55,7 @@ import { normalizeWorkspaceAppAudience, workspaceAppAudienceFromEnv, workspaceAp
55
55
  import { isValidWorkspaceAppIdFormat } from "../shared/workspace-app-id.js";
56
56
  import { injectAnalyticsIntoHtml } from "./analytics.js";
57
57
  import { getConfiguredAppBasePath } from "./app-base-path.js";
58
+ import { getAppProductionUrl } from "./app-url.js";
58
59
  import { readAnalyticsAnonymousId, signupAttributionFromCookieHeader, } from "./attribution.js";
59
60
  import { getAuthLoginMode } from "./auth-login-mode.js";
60
61
  import { createBetterAuthSessionForEmail, ensureGoogleAuthIdentity, getBetterAuth, getBetterAuthSync, isDeployPreview, } from "./better-auth-instance.js";
@@ -64,10 +65,7 @@ import { getAllowedCorsOrigin, readCorsAllowedOrigins, } from "./cors-origins.js
64
65
  import { readDesktopSso, writeDesktopSso, clearDesktopSso, } from "./desktop-sso.js";
65
66
  import { resolveGoogleSignInCredentials } from "./google-oauth-credentials.js";
66
67
  import { isElectron as isElectronRequest, getAppBasePath, getAppUrl, getOrigin, encodeOAuthState, decodeOAuthState, createOAuthSession, oauthCallbackResponse, oauthDesktopExchangePage, oauthErrorPage, resolveOAuthRedirectUri, isAllowedOAuthRedirectUri, } from "./google-oauth.js";
67
- // Pure env-read feature switch from a leaf module (no dependency back on
68
- // auth.ts), so the guard and the SSO route handler share one validator and
69
- // can never disagree about whether federated SSO is enabled.
70
- import { isIdentitySsoEnabled } from "./identity-sso-store.js";
68
+ import { isCanonicalAgentNativeAppRequest, isDesktopSsoCanaryUserAgent, isIdentitySsoEnabled, } from "./identity-sso-store.js";
71
69
  import { ensureCanonicalUserForLegacySession } from "./legacy-auth-migration.js";
72
70
  import { safeOAuthReturnUrl } from "./oauth-return-url.js";
73
71
  import { getOnboardingHtml, getResetPasswordHtml, } from "./onboarding-html.js";
@@ -312,6 +310,23 @@ export function isDevEnvironment() {
312
310
  export function safeReturnPath(raw) {
313
311
  return normalizeAppPath(raw) ?? "/";
314
312
  }
313
+ // Better Auth's relative callback validator is stricter than normalizeAppPath:
314
+ // query values such as UTM labels may contain characters that are safe here but
315
+ // invalid as a Better Auth relative callback. Promote those paths to the
316
+ // canonical app origin so the callback remains same-origin and valid there.
317
+ const BETTER_AUTH_RELATIVE_CALLBACK_PATH_RE = /^\/(?!\/|\\|%2f|%5c)[\w\-.\+/@]*(?:\?[\w\-.\+/=&%@]*)?$/i;
318
+ function betterAuthCallbackURL(raw, forceAbsolute = false, event) {
319
+ const safePath = safeReturnPath(raw);
320
+ if (!forceAbsolute && BETTER_AUTH_RELATIVE_CALLBACK_PATH_RE.test(safePath)) {
321
+ return safePath;
322
+ }
323
+ try {
324
+ return new URL(safePath, getAppProductionUrl(event)).toString();
325
+ }
326
+ catch {
327
+ return "/";
328
+ }
329
+ }
315
330
  /**
316
331
  * Return the configured login HTML for this request, or `null` when no auth
317
332
  * guard is installed. Used by the `/_agent-native/open` deep-link route to
@@ -1693,13 +1708,16 @@ function createAuthGuardFn() {
1693
1708
  // definition, NOT yet signed in to THIS app) must bypass the blanket
1694
1709
  // 401-for-/_agent-native/*: they resolve / mint the browser session
1695
1710
  // themselves and verify a signature-bound, single-use, CSRF-stated
1696
- // hub token — not a cookie. This bypass is GATED on the opt-in env var
1697
- // so an unset `AGENT_NATIVE_IDENTITY_HUB_URL` is a true no-op (the
1698
- // guard's behaviour is byte-for-byte unchanged when SSO is off). The
1699
- // handler itself 404s when disabled as defence in depth.
1700
- if (isIdentitySsoEnabled() &&
1701
- (p === "/_agent-native/identity/login" ||
1702
- p === "/_agent-native/identity/callback")) {
1711
+ // hub token — not a cookie. The handler fails closed with 404 unless
1712
+ // direct web SSO is configured or this is the packaged SSO Canary on a
1713
+ // canonical app origin. Keeping the bypass exact lets that request-scoped
1714
+ // decision happen without exposing any other identity subpath.
1715
+ const isIdentitySsoEntryPath = p === "/_agent-native/identity/login" ||
1716
+ p === "/_agent-native/identity/callback";
1717
+ const isDesktopCanaryIdentityRequest = isDesktopSsoCanaryUserAgent(getHeader(event, "user-agent")) &&
1718
+ isCanonicalAgentNativeAppRequest(getHeader(event, "host"), getHeader(event, "x-forwarded-proto"));
1719
+ if (isIdentitySsoEntryPath &&
1720
+ (isIdentitySsoEnabled() || isDesktopCanaryIdentityRequest)) {
1703
1721
  return;
1704
1722
  }
1705
1723
  // Internal processor endpoint for the A2A async-mode fanout. Mirrors the
@@ -2971,6 +2989,7 @@ async function mountBetterAuthRoutes(app, options) {
2971
2989
  // need for a separate "Connect Google" page.
2972
2990
  const betterAuthConfig = {
2973
2991
  ...(options.betterAuth ?? {}),
2992
+ ...(options.maxAge !== undefined ? { sessionMaxAge: options.maxAge } : {}),
2974
2993
  ...(options.googleScopes ? { googleScopes: options.googleScopes } : {}),
2975
2994
  };
2976
2995
  const auth = await getBetterAuth(betterAuthConfig);
@@ -3046,10 +3065,13 @@ async function mountBetterAuthRoutes(app, options) {
3046
3065
  }
3047
3066
  }
3048
3067
  // The signup wrapper sanitizes callbackURL before calling Better Auth,
3049
- // but the resend endpoint is exposed directly so users can request a
3050
- // fresh link while unauthenticated. Keep that path equally strict:
3051
- // only same-origin relative return paths survive into the email.
3052
- if (isSendVerificationEmail || isMagicLinkRequest) {
3068
+ // but the direct email and magic-link endpoints are also reachable from
3069
+ // the browser. Keep every callback path valid for Better Auth's own
3070
+ // stricter relative URL validator before it is embedded in an email.
3071
+ if (isSendVerificationEmail ||
3072
+ isMagicLinkRequest ||
3073
+ reqPath.includes("/sign-up/email") ||
3074
+ reqPath.includes("/sign-in/email")) {
3053
3075
  try {
3054
3076
  const body = (await authRequest
3055
3077
  .clone()
@@ -3064,7 +3086,7 @@ async function mountBetterAuthRoutes(app, options) {
3064
3086
  for (const key of callbackKeys) {
3065
3087
  if (typeof body[key] !== "string")
3066
3088
  continue;
3067
- const callbackURL = safeReturnPath(body[key]);
3089
+ const callbackURL = betterAuthCallbackURL(body[key], false, event);
3068
3090
  if (callbackURL !== body[key]) {
3069
3091
  sanitizedBody[key] = callbackURL;
3070
3092
  changed = true;
@@ -3273,7 +3295,7 @@ async function mountBetterAuthRoutes(app, options) {
3273
3295
  const body = await readBody(event);
3274
3296
  const rawEmail = typeof body?.email === "string" ? body.email : "";
3275
3297
  const email = normalizeAuthEmail(rawEmail);
3276
- let callbackURL = typeof body?.callbackURL === "string"
3298
+ let callbackPath = typeof body?.callbackURL === "string"
3277
3299
  ? safeReturnPath(body.callbackURL)
3278
3300
  : "/";
3279
3301
  let desktopFlow;
@@ -3286,15 +3308,17 @@ async function mountBetterAuthRoutes(app, options) {
3286
3308
  return { error: GOOGLE_AUTH_REQUIRED_MESSAGE };
3287
3309
  }
3288
3310
  try {
3289
- if (isDesktopMagicLinkCallbackPath(callbackURL)) {
3311
+ if (isDesktopMagicLinkCallbackPath(callbackPath)) {
3290
3312
  desktopFlow = await issueDesktopMagicLinkFlow();
3291
- callbackURL = withDesktopMagicLinkFlow(callbackURL, desktopFlow);
3313
+ callbackPath = withDesktopMagicLinkFlow(callbackPath, desktopFlow);
3292
3314
  }
3315
+ const callbackURL = betterAuthCallbackURL(callbackPath, false, event);
3316
+ const newUserCallbackPath = `${getAppBasePath()}/_agent-native/auth/magic-link/new-user?return=${encodeURIComponent(callbackPath)}`;
3293
3317
  await auth.api.signInMagicLink({
3294
3318
  body: {
3295
3319
  email,
3296
3320
  callbackURL,
3297
- newUserCallbackURL: `${getAppBasePath()}/_agent-native/auth/magic-link/new-user?return=${encodeURIComponent(callbackURL)}`,
3321
+ newUserCallbackURL: betterAuthCallbackURL(newUserCallbackPath, callbackURL !== callbackPath, event),
3298
3322
  },
3299
3323
  headers: event.headers,
3300
3324
  });
@@ -3323,7 +3347,7 @@ async function mountBetterAuthRoutes(app, options) {
3323
3347
  const email = normalizeAuthEmail(rawEmail);
3324
3348
  const password = body?.password;
3325
3349
  const callbackURL = typeof body?.callbackURL === "string"
3326
- ? safeReturnPath(body.callbackURL)
3350
+ ? betterAuthCallbackURL(body.callbackURL, false, event)
3327
3351
  : "/";
3328
3352
  if (!email) {
3329
3353
  setResponseStatus(event, 400);
@@ -118,6 +118,8 @@ export interface BetterAuthInstance {
118
118
  export interface BetterAuthConfig {
119
119
  /** Base path for Better Auth routes. Default: "/_agent-native/auth/ba" */
120
120
  basePath?: string;
121
+ /** Session max age in seconds. Defaults to the framework's 30-day lifetime. */
122
+ sessionMaxAge?: number;
121
123
  /** Additional social providers beyond what env vars auto-detect */
122
124
  socialProviders?: BetterAuthOptions["socialProviders"];
123
125
  /** Additional Better Auth plugins */
@@ -1048,8 +1048,8 @@ async function createBetterAuthInstance(config) {
1048
1048
  },
1049
1049
  },
1050
1050
  session: {
1051
- expiresIn: 60 * 60 * 24 * 30, // 30 days
1052
- updateAge: 60 * 60 * 24, // refresh daily
1051
+ expiresIn: config?.sessionMaxAge ?? 60 * 60 * 24 * 30,
1052
+ updateAge: Math.min(60 * 60 * 24, config?.sessionMaxAge ?? 60 * 60 * 24 * 30), // refresh daily, or sooner for short custom sessions
1053
1053
  cookieCache: {
1054
1054
  enabled: true,
1055
1055
  maxAge: 5 * 60, // 5 min cache
@@ -293,6 +293,7 @@ export declare function readLegacyCoreRouteInitSettings(readSetting?: CoreRouteS
293
293
  * their cold-start budget on legacy cleanup or best-effort table warmups.
294
294
  */
295
295
  export declare function shouldRunCoreRouteBootDatabaseWork(env?: NodeJS.ProcessEnv): boolean;
296
+ export declare function ensureS3FileUploadProvider(): void;
296
297
  export declare function createCoreRoutesPlugin(options?: CoreRoutesPluginOptions): NitroPluginDef;
297
298
  /**
298
299
  * Default core routes plugin — mount with no configuration needed.
@@ -11,7 +11,8 @@ import { mountDbAdminRoutes } from "../db-admin/routes.js";
11
11
  import { getDbExec, isProductionServerlessFunctionRuntime, } from "../db/client.js";
12
12
  import { getDatabaseRuntimeFingerprint, getRuntimeDebugFingerprint, runDatabaseSchemaHealthCheck, } from "../db/runtime-diagnostics.js";
13
13
  import { ssrfSafeFetch } from "../extensions/url-safety.js";
14
- import { uploadFile, getActiveFileUploadProviderForRequest, listFileUploadProviders, } from "../file-upload/index.js";
14
+ import { uploadFile, getActiveFileUploadProviderForRequest, listFileUploadProviders, registerFileUploadProvider, } from "../file-upload/index.js";
15
+ import { s3FileUploadProvider } from "../file-upload/s3.js";
15
16
  import { handleMcpConnect } from "../mcp/connect-route.js";
16
17
  import { handleMcpOAuth, handleMcpOAuthAuthorizationServerMetadata, handleMcpOAuthProtectedResourceMetadata, } from "../mcp/oauth-route.js";
17
18
  import { MCP_ROUTE_PREFIXES } from "../mcp/route-paths.js";
@@ -51,7 +52,6 @@ import { createGatewayAccessCheckHandler } from "./gateway-access-check.js";
51
52
  import { getAppBasePath, getOrigin } from "./google-oauth.js";
52
53
  import { createGoogleRealtimeSessionHandler } from "./google-realtime-session.js";
53
54
  import { readBody, DEFAULT_UPLOAD_MAX_FILE_BYTES, isAllowedUploadMimeType, } from "./h3-helpers.js";
54
- import { isIdentitySsoEnabled } from "./identity-sso-store.js";
55
55
  import { handleIdentitySso } from "./identity-sso.js";
56
56
  import { createOpenRouteHandler } from "./open-route.js";
57
57
  import { createPollEventsHandler } from "./poll-events.js";
@@ -889,6 +889,12 @@ function wireRouteErrorCapture(nitroApp) {
889
889
  }
890
890
  });
891
891
  }
892
+ export function ensureS3FileUploadProvider() {
893
+ if (listFileUploadProviders().some((provider) => provider.id === s3FileUploadProvider.id)) {
894
+ return;
895
+ }
896
+ registerFileUploadProvider(s3FileUploadProvider);
897
+ }
892
898
  export function createCoreRoutesPlugin(options = {}) {
893
899
  return async (nitroApp) => {
894
900
  markDefaultPluginProvided(nitroApp, "core-routes");
@@ -905,6 +911,12 @@ export function createCoreRoutesPlugin(options = {}) {
905
911
  });
906
912
  try {
907
913
  const P = FRAMEWORK_ROUTE_PREFIX;
914
+ // Keep the framework-owned S3-compatible provider available even when an
915
+ // app does not mount the optional onboarding plugin. The settings CTA and
916
+ // the upload route share this registry. An app may register its own
917
+ // provider under the conventional `s3` id, so preserve that explicit
918
+ // registration instead of replacing it during core bootstrap.
919
+ ensureS3FileUploadProvider();
908
920
  // This response is a side-effect-free static contract used by the SSR
909
921
  // shell. Mount it before optional default-plugin/bootstrap work so a
910
922
  // browser's automatic rules fetch cannot inherit the cold-start wait.
@@ -3077,22 +3089,20 @@ export function createCoreRoutesPlugin(options = {}) {
3077
3089
  }));
3078
3090
  }
3079
3091
  }
3080
- // Cross-app SSO ("Sign in with Agent-Native") — CLIENT side. Mounted
3081
- // ONLY when `AGENT_NATIVE_IDENTITY_HUB_URL` is set, so an unset env var
3082
- // means the route is never even registered: zero new surface, existing
3083
- // auth byte-for-byte unchanged. `/login` 302s to the identity hub;
3092
+ // Cross-app SSO ("Sign in with Agent-Native") — CLIENT side. `/login`
3093
+ // 302s to the identity hub;
3084
3094
  // `/callback` verifies the hub-issued A2A-signed identity JWT and JIT-
3085
3095
  // links the verified email into this app's local Better Auth store. The
3086
- // handler 404s if disabled (defence in depth). The auth guard bypasses
3087
- // these two exact paths under the same env gate.
3088
- if (isIdentitySsoEnabled()) {
3089
- getH3App(nitroApp).use(`${P}/identity`, defineEventHandler(async (event) => {
3090
- // Framework strips the mount prefix; what remains is the subpath
3091
- // after `/identity` (e.g. `/login`, `/callback`).
3092
- const subpath = event.url?.pathname || "";
3093
- return handleIdentitySso(event, subpath);
3094
- }));
3095
- }
3096
+ // handler fails closed unless direct web SSO is configured or the
3097
+ // packaged Desktop SSO Canary requests a canonical Agent Native app.
3098
+ // Mounting the handler unconditionally lets that request-scoped decision
3099
+ // work.
3100
+ getH3App(nitroApp).use(`${P}/identity`, defineEventHandler(async (event) => {
3101
+ // Framework strips the mount prefix; what remains is the subpath
3102
+ // after `/identity` (e.g. `/login`, `/callback`).
3103
+ const subpath = event.url?.pathname || "";
3104
+ return handleIdentitySso(event, subpath);
3105
+ }));
3096
3106
  if (!options.disableOpenRoute) {
3097
3107
  // Stable deep-link route. External agents (MCP/A2A) surface
3098
3108
  // `/_agent-native/open?app=…&view=…&<recordId>=…` links; this resolves
@@ -35,6 +35,9 @@ export declare function getIdentityHubUrl(): string | undefined;
35
35
  * env-unset-no-op invariant is asserted against.
36
36
  */
37
37
  export declare function isIdentitySsoEnabled(): boolean;
38
+ export declare function isDesktopSsoCanaryUserAgent(userAgent: string | undefined): boolean;
39
+ export declare function isCanonicalAgentNativeAppOrigin(origin: string | undefined): boolean;
40
+ export declare function isCanonicalAgentNativeAppRequest(host: string | undefined, forwardedProtocol: string | undefined): boolean;
38
41
  /**
39
42
  * The conditional "Sign in with Agent-Native" entry injected into the login
40
43
  * page — ONLY when the feature is enabled. Returns an empty string when
@@ -25,6 +25,25 @@ import { randomBytes } from "node:crypto";
25
25
  import { getDbExec, isConnectionError, intType, isPostgres, } from "../db/client.js";
26
26
  import { ensureTableExists } from "../db/ddl-guard.js";
27
27
  let _initPromise;
28
+ const DESKTOP_SSO_CANARY_USER_AGENT = /AgentNativeDesktopSsoCanary\//i;
29
+ const CANONICAL_IDENTITY_SSO_APP_ORIGINS = new Set([
30
+ "https://analytics.agent-native.com",
31
+ "https://assets.agent-native.com",
32
+ "https://brain.agent-native.com",
33
+ "https://calendar.agent-native.com",
34
+ "https://chat.agent-native.com",
35
+ "https://clips.agent-native.com",
36
+ "https://content.agent-native.com",
37
+ "https://crm.agent-native.com",
38
+ "https://design.agent-native.com",
39
+ "https://dispatch.agent-native.com",
40
+ "https://forms.agent-native.com",
41
+ "https://macros.agent-native.com",
42
+ "https://mail.agent-native.com",
43
+ "https://plan.agent-native.com",
44
+ "https://slides.agent-native.com",
45
+ "https://tasks.agent-native.com",
46
+ ]);
28
47
  // ---------------------------------------------------------------------------
29
48
  // Feature switch — the SINGLE source of truth for whether the federated-SSO
30
49
  // client is active. Lives here (a leaf module with no dependency on auth.ts)
@@ -61,6 +80,32 @@ export function getIdentityHubUrl() {
61
80
  export function isIdentitySsoEnabled() {
62
81
  return !!getIdentityHubUrl();
63
82
  }
83
+ export function isDesktopSsoCanaryUserAgent(userAgent) {
84
+ return DESKTOP_SSO_CANARY_USER_AGENT.test(userAgent ?? "");
85
+ }
86
+ export function isCanonicalAgentNativeAppOrigin(origin) {
87
+ if (!origin)
88
+ return false;
89
+ try {
90
+ const parsed = new URL(origin);
91
+ return (parsed.protocol === "https:" &&
92
+ !parsed.username &&
93
+ !parsed.password &&
94
+ parsed.pathname === "/" &&
95
+ !parsed.search &&
96
+ !parsed.hash &&
97
+ CANONICAL_IDENTITY_SSO_APP_ORIGINS.has(parsed.origin));
98
+ }
99
+ catch {
100
+ return false;
101
+ }
102
+ }
103
+ export function isCanonicalAgentNativeAppRequest(host, forwardedProtocol) {
104
+ if (!host || forwardedProtocol !== "https") {
105
+ return false;
106
+ }
107
+ return isCanonicalAgentNativeAppOrigin(`https://${host}`);
108
+ }
64
109
  /**
65
110
  * The conditional "Sign in with Agent-Native" entry injected into the login
66
111
  * page — ONLY when the feature is enabled. Returns an empty string when
@@ -6,12 +6,15 @@
6
6
  * an identity authority (Dispatch) so a user logged in there can land in this
7
7
  * app without re-entering credentials.
8
8
  *
9
- * Opt-in, OFF by default, fully reversible. Everything here is gated on the
10
- * single env var `AGENT_NATIVE_IDENTITY_HUB_URL`:
9
+ * Opt-in, OFF by default, fully reversible. Direct web federation is gated on
10
+ * `AGENT_NATIVE_IDENTITY_HUB_URL`; the packaged Desktop SSO Canary may use the
11
+ * canonical Dispatch authority on canonical hosted apps, where Dispatch's
12
+ * default-off feature flag controls rollout:
11
13
  *
12
- * - UNSET → `isIdentitySsoEnabled()` is false. The route handler 404s, the
13
- * auth-guard bypass does not apply, and the login page renders no SSO
14
- * button. Existing auth is byte-for-byte unchanged.
14
+ * - UNSET → normal browser requests remain protected and the login page
15
+ * renders no SSO button. Packaged Canary requests on canonical app origins
16
+ * may reach the flow, but Dispatch refuses them unless its rollout flag
17
+ * allows the user.
15
18
  * - SET (e.g. `https://dispatch.agent-native.com`) → two routes mount:
16
19
  * GET /_agent-native/identity/login
17
20
  * 302 → `<HUB>/_agent-native/identity/authorize?app=<id>
@@ -59,6 +62,15 @@ export declare const IDENTITY_SSO_PROVIDER_ID = "agent-native";
59
62
  * as an identity assertion.
60
63
  */
61
64
  export declare const IDENTITY_SSO_SCOPE = "identity";
65
+ export declare const IDENTITY_SSO_DESKTOP_COMPLETE_PATH = "/_agent-native/identity/desktop-complete";
66
+ /**
67
+ * Direct web federation stays explicitly configured through
68
+ * `AGENT_NATIVE_IDENTITY_HUB_URL`. The packaged Desktop SSO Canary may use the
69
+ * canonical Dispatch authority without per-app deployment configuration, but
70
+ * only for canonical HTTPS Agent Native app origins. Dispatch's default-off
71
+ * feature flag remains the authoritative rollout gate.
72
+ */
73
+ export declare function resolveIdentityHubUrl(event: H3Event): string | undefined;
62
74
  /**
63
75
  * Handle a `/_agent-native/identity/*` request. `subpath` is the part after
64
76
  * `/identity` (e.g. `/login`, `/callback`). Returns a 404 Response whenever
@@ -68,10 +80,8 @@ export declare const IDENTITY_SSO_SCOPE = "identity";
68
80
  export declare function handleIdentitySso(event: H3Event, subpath: string): Promise<Response>;
69
81
  /**
70
82
  * Whether the given (already base-path-stripped) request path is one of the
71
- * SSO routes that must bypass the blanket auth guard. Both routes resolve /
72
- * mint the browser session themselves: `/login` is the unauthenticated entry
73
- * point, and `/callback` is hit by a user who is (by definition) not yet
74
- * signed in to THIS app. Returns false when the feature is disabled, so the
75
- * guard's behaviour is unchanged with the env unset.
83
+ * two SSO routes that must bypass the blanket auth guard. The handler makes
84
+ * the request-scoped enablement decision and fails closed with 404; no other
85
+ * identity subpath bypasses authentication.
76
86
  */
77
87
  export declare function isIdentitySsoBypassPath(p: string): boolean;