@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.
- package/corpus/README.md +1 -1
- package/corpus/templates/analytics/.agents/skills/delegate-to-agent/SKILL.md +28 -0
- package/corpus/templates/analytics/.agents/skills/frontend-design/SKILL.md +5 -0
- package/corpus/templates/analytics/app/hooks/use-navigation-state.ts +83 -45
- package/corpus/templates/analytics/changelog/2026-08-11-analytics-dashboards-keep-the-selected-tab-when-reopened.md +6 -0
- package/corpus/templates/assets/.agents/skills/delegate-to-agent/SKILL.md +28 -0
- package/corpus/templates/assets/.agents/skills/frontend-design/SKILL.md +5 -0
- package/corpus/templates/brain/.agents/skills/delegate-to-agent/SKILL.md +28 -0
- package/corpus/templates/brain/.agents/skills/frontend-design/SKILL.md +5 -0
- package/corpus/templates/calendar/.agents/skills/delegate-to-agent/SKILL.md +28 -0
- package/corpus/templates/calendar/.agents/skills/frontend-design/SKILL.md +5 -0
- package/corpus/templates/chat/.agents/skills/delegate-to-agent/SKILL.md +28 -0
- package/corpus/templates/chat/.agents/skills/frontend-design/SKILL.md +5 -0
- package/corpus/templates/clips/.agents/skills/delegate-to-agent/SKILL.md +28 -0
- package/corpus/templates/clips/.agents/skills/frontend-design/SKILL.md +5 -0
- package/corpus/templates/clips/changelog/2026-08-11-clips-recovers-from-transient-updates-and-avoids-macos-priva.md +6 -0
- package/corpus/templates/clips/desktop/src/app.tsx +32 -176
- package/corpus/templates/clips/desktop/src/lib/updater.ts +52 -37
- package/corpus/templates/clips/desktop/src/styles.css +1 -166
- package/corpus/templates/clips/desktop/src-tauri/Cargo.toml +2 -0
- package/corpus/templates/clips/desktop/src-tauri/Info.plist +4 -0
- package/corpus/templates/clips/desktop/src-tauri/src/eventkit.rs +28 -1
- package/corpus/templates/clips/desktop/src-tauri/src/lib.rs +2 -0
- package/corpus/templates/clips/desktop/src-tauri/src/native_speech.rs +48 -1
- package/corpus/templates/clips/desktop/src-tauri/src/permission_status.rs +3 -0
- package/corpus/templates/clips/desktop/src-tauri/src/whisper_speech.rs +5 -0
- package/corpus/templates/clips/server/plugins/auth.ts +3 -0
- package/corpus/templates/content/.agents/skills/delegate-to-agent/SKILL.md +28 -0
- package/corpus/templates/content/.agents/skills/frontend-design/SKILL.md +5 -0
- package/corpus/templates/content/actions/_document-discovery-query.ts +127 -0
- package/corpus/templates/content/actions/list-documents.ts +189 -198
- package/corpus/templates/content/actions/search-documents.ts +95 -24
- package/corpus/templates/content/app/components/editor/CommentsSidebar.tsx +2 -1
- package/corpus/templates/content/app/hooks/use-documents.ts +84 -6
- package/corpus/templates/content/shared/api.ts +10 -0
- package/corpus/templates/design/.agents/skills/delegate-to-agent/SKILL.md +28 -0
- package/corpus/templates/design/.agents/skills/frontend-design/SKILL.md +5 -0
- package/corpus/templates/design/app/pages/DesignSystemSetup.tsx +5 -1
- package/corpus/templates/design/changelog/2026-08-11-design-agent-prompts-copy-successfully-in-the-desktop-app.md +6 -0
- package/corpus/templates/dispatch/.agents/skills/delegate-to-agent/SKILL.md +28 -0
- package/corpus/templates/dispatch/.agents/skills/frontend-design/SKILL.md +5 -0
- package/corpus/templates/dispatch/app/global.css +2 -2
- package/corpus/templates/dispatch/changelog/2026-08-10-desktop-workspace-sign-in.md +6 -0
- package/corpus/templates/dispatch/changelog/2026-08-11-dispatch-no-longer-shows-the-generic-chat-starter-among-defa.md +6 -0
- package/corpus/templates/dispatch/changelog/2026-08-11-integrations-and-scheduled-work-open-as-first-class-electron-pages.md +6 -0
- package/corpus/templates/dispatch/changelog/2026-08-11-sidebar-text-is-slightly-easier-to-read-in-light-and-dark-mo.md +6 -0
- package/corpus/templates/dispatch/server/lib/identity-sso.ts +57 -31
- package/corpus/templates/dispatch/server/plugins/feature-flags.ts +5 -0
- package/corpus/templates/dispatch/server/plugins/identity-sso.ts +82 -33
- package/corpus/templates/dispatch/server/plugins/org-apps-directory.ts +7 -15
- package/corpus/templates/dispatch/server/plugins/setup-dispatch.ts +9 -1
- package/corpus/templates/dispatch/shared/feature-flags.ts +15 -0
- package/corpus/templates/factory/.agents/skills/delegate-to-agent/SKILL.md +28 -0
- package/corpus/templates/factory/.agents/skills/frontend-design/SKILL.md +5 -0
- package/corpus/templates/forms/.agents/skills/delegate-to-agent/SKILL.md +28 -0
- package/corpus/templates/forms/.agents/skills/form-responses/SKILL.md +8 -7
- package/corpus/templates/forms/.agents/skills/frontend-design/SKILL.md +5 -0
- package/corpus/templates/forms/app/hooks/use-forms.ts +8 -1
- package/corpus/templates/forms/changelog/2026-08-11-fixed-public-forms-so-conditional-questions-stay-hidden-unti.md +6 -0
- package/corpus/templates/forms/server/handlers/submissions.ts +2 -1
- package/corpus/templates/forms/server/lib/public-form-ssr.ts +37 -2
- package/corpus/templates/forms/shared/page-url.ts +54 -0
- package/corpus/templates/forms/shared/types.ts +4 -4
- package/corpus/templates/macros/.agents/skills/frontend-design/SKILL.md +5 -0
- package/corpus/templates/mail/.agents/skills/delegate-to-agent/SKILL.md +28 -0
- package/corpus/templates/mail/.agents/skills/frontend-design/SKILL.md +5 -0
- package/corpus/templates/plan/.agents/skills/delegate-to-agent/SKILL.md +28 -0
- package/corpus/templates/plan/.agents/skills/frontend-design/SKILL.md +5 -0
- package/corpus/templates/slides/.agents/skills/delegate-to-agent/SKILL.md +28 -0
- package/corpus/templates/slides/.agents/skills/frontend-design/SKILL.md +5 -0
- package/corpus/templates/slides/actions/add-slide.ts +0 -27
- package/corpus/templates/slides/actions/import-file.ts +28 -9
- package/corpus/templates/slides/actions/view-screen.ts +4 -4
- package/corpus/templates/slides/app/components/design-system/DesignSystemSetup.tsx +8 -1
- package/corpus/templates/slides/app/components/editor/AiEditingMarker.tsx +25 -0
- package/corpus/templates/slides/app/components/editor/EditorSidebar.tsx +43 -48
- package/corpus/templates/slides/app/components/editor/EditorToolbar.tsx +9 -6
- package/corpus/templates/slides/app/components/editor/GeneratingSlidePreview.tsx +1 -9
- package/corpus/templates/slides/app/components/editor/ImageDropPromptPopover.tsx +2 -0
- package/corpus/templates/slides/app/components/editor/ImageOverlay.tsx +0 -26
- package/corpus/templates/slides/app/components/editor/SlideEditor.tsx +904 -217
- package/corpus/templates/slides/app/components/editor/canvas-interactions/index.ts +1 -0
- package/corpus/templates/slides/app/components/editor/canvas-interactions/slides-canvas-adapter.ts +11 -0
- package/corpus/templates/slides/app/components/editor/inline-edit-session.ts +16 -0
- package/corpus/templates/slides/app/components/editor/slide-object-interactions.ts +22 -6
- package/corpus/templates/slides/app/components/editor/style-clipboard.ts +61 -0
- package/corpus/templates/slides/app/components/layout/Layout.tsx +26 -2
- package/corpus/templates/slides/app/components/ui/context-menu.tsx +1 -0
- package/corpus/templates/slides/app/context/DeckContext.tsx +75 -25
- package/corpus/templates/slides/app/global.css +1 -1
- package/corpus/templates/slides/app/i18n/en-US.ts +6 -1
- package/corpus/templates/slides/app/lib/create-deck-generation.ts +1 -1
- package/corpus/templates/slides/app/lib/image-drop-to-agent.ts +12 -12
- package/corpus/templates/slides/app/lib/slide-agent-context.ts +52 -0
- package/corpus/templates/slides/app/lib/slide-image-replacement.ts +61 -0
- package/corpus/templates/slides/app/pages/DeckEditor.tsx +55 -116
- package/corpus/templates/slides/app/pages/Index.tsx +28 -3
- package/corpus/templates/slides/changelog/2026-08-11-agent-chat-now-follows-the-current-slide-and-selection.md +6 -0
- package/corpus/templates/slides/changelog/2026-08-11-deck-titles-now-use-slide-content-instead-of-placeholder-filenames.md +6 -0
- package/corpus/templates/slides/changelog/2026-08-11-history-now-opens-from-the-deck-overflow-menu.md +6 -0
- package/corpus/templates/slides/changelog/2026-08-11-images-can-be-dropped-directly-onto-slides-and-resized-or-re.md +6 -0
- package/corpus/templates/slides/changelog/2026-08-11-new-decks-now-transition-directly-to-a-full-page-editor-load.md +6 -0
- package/corpus/templates/slides/changelog/2026-08-11-selected-slide-layers-can-be-nudged-precisely-with-arrow-key.md +6 -0
- package/corpus/templates/slides/changelog/2026-08-11-slides-can-copy-and-paste-element-styles-with-cmd-option-c-v.md +6 -0
- package/corpus/templates/slides/changelog/2026-08-11-slides-shows-one-compact-ai-marker-and-keeps-your-current-sl.md +6 -0
- package/corpus/templates/slides/changelog/2026-08-11-text-edits-preserve-slide-layout-when-no-changes-are-made.md +6 -0
- package/corpus/templates/slides/changelog/2026-08-11-the-style-toolbar-now-uses-the-full-available-width.md +6 -0
- package/corpus/templates/slides/changelog/2026-08-11-undo-and-redo-now-move-one-visible-slide-state-at-a-time.md +6 -0
- package/corpus/templates/slides/server/lib/chat-attachments.ts +6 -2
- package/corpus/templates/slides/shared/deck-title.ts +56 -0
- package/corpus/templates/tasks/.agents/skills/delegate-to-agent/SKILL.md +28 -0
- package/corpus/templates/tasks/.agents/skills/frontend-design/SKILL.md +5 -0
- package/dist/agent/run-store.js +6 -1
- package/dist/agent/thread-data-builder.js +19 -44
- package/dist/agent/types.d.ts +13 -0
- package/dist/catalog.json +1 -0
- package/dist/cli/create.js +1 -1
- package/dist/client/AssistantChat.js +58 -10
- package/dist/client/FileStorageSetupCard.d.ts +6 -0
- package/dist/client/FileStorageSetupCard.js +18 -0
- package/dist/client/NewWorkspaceAppFlow.js +10 -0
- package/dist/client/agent-chat-adapter.js +87 -11
- package/dist/client/agent-chat.d.ts +1 -1
- package/dist/client/agent-chat.js +8 -3
- package/dist/client/chat/attachment-adapters.js +10 -0
- package/dist/client/chat/message-components.d.ts +4 -1
- package/dist/client/chat/message-components.js +37 -13
- package/dist/client/chat/tool-call-display.js +14 -0
- package/dist/client/chat-first/apps-rail.d.ts +1 -1
- package/dist/client/chat-first/apps-rail.js +6 -6
- package/dist/client/chat-first/copy.js +1 -0
- package/dist/client/chat-first/types.d.ts +1 -0
- package/dist/client/extensions/EmbeddedExtension.js +1 -1
- package/dist/client/extensions/ExtensionViewer.js +1 -1
- package/dist/client/extensions/InlineExtensionFrame.js +1 -1
- package/dist/client/onboarding/FirstRunOnboarding.js +17 -2
- package/dist/client/settings/FileStorageSettingsForm.d.ts +2 -0
- package/dist/client/settings/FileStorageSettingsForm.js +113 -0
- package/dist/client/settings/SettingsPanel.js +2 -1
- package/dist/client/sse-event-processor.js +21 -0
- package/dist/extensions/actions.js +2 -2
- package/dist/extensions/html-shell.js +3 -1
- package/dist/file-upload/pre-upload-attachments.d.ts +15 -10
- package/dist/file-upload/pre-upload-attachments.js +68 -24
- package/dist/file-upload/registry.d.ts +4 -5
- package/dist/file-upload/registry.js +7 -14
- package/dist/file-upload/s3.d.ts +9 -0
- package/dist/file-upload/s3.js +168 -0
- package/dist/file-upload/types.d.ts +3 -3
- package/dist/file-upload/types.js +2 -2
- package/dist/onboarding/app-profile.js +23 -1
- package/dist/onboarding/default-steps.js +69 -0
- package/dist/onboarding/types.d.ts +2 -0
- package/dist/progress/routes.d.ts +1 -1
- package/dist/provider-api/actions/custom-provider-registration.d.ts +11 -11
- package/dist/provider-api/actions/provider-api.d.ts +8 -8
- package/dist/resources/handlers.d.ts +1 -1
- package/dist/secrets/routes.d.ts +6 -6
- package/dist/server/agent-chat/browser-team-tools.js +20 -0
- package/dist/server/agent-chat-plugin.js +12 -3
- package/dist/server/auth.js +45 -21
- package/dist/server/better-auth-instance.d.ts +2 -0
- package/dist/server/better-auth-instance.js +2 -2
- package/dist/server/core-routes-plugin.d.ts +1 -0
- package/dist/server/core-routes-plugin.js +26 -16
- package/dist/server/identity-sso-store.d.ts +3 -0
- package/dist/server/identity-sso-store.js +45 -0
- package/dist/server/identity-sso.d.ts +20 -10
- package/dist/server/identity-sso.js +79 -31
- package/dist/server/index.d.ts +1 -1
- package/dist/server/index.js +1 -1
- package/dist/templates/chat/.agents/skills/delegate-to-agent/SKILL.md +28 -0
- package/dist/templates/chat/.agents/skills/frontend-design/SKILL.md +5 -0
- package/dist/templates/default/.agents/skills/delegate-to-agent/SKILL.md +28 -0
- package/dist/templates/default/.agents/skills/frontend-design/SKILL.md +5 -0
- package/dist/templates/workspace-core/.agents/skills/authentication/SKILL.md +24 -1
- package/dist/templates/workspace-core/.agents/skills/delegate-to-agent/SKILL.md +28 -0
- package/dist/templates/workspace-core/.agents/skills/extensions/SKILL.md +6 -2
- package/dist/templates/workspace-core/.agents/skills/extensions/references/api.md +1 -1
- package/dist/templates/workspace-core/.agents/skills/frontend-design/SKILL.md +5 -0
- package/dist/templates/workspace-core/.agents/skills/generative-ui/SKILL.md +3 -1
- package/docs/content/authentication.mdx +27 -0
- package/docs/content/cross-app-sso.mdx +38 -8
- package/docs/content/extensions.mdx +15 -15
- package/docs/content/file-uploads.mdx +10 -12
- package/docs/content/generative-ui.mdx +6 -1
- package/package.json +2 -2
- package/src/templates/chat/.agents/skills/delegate-to-agent/SKILL.md +28 -0
- package/src/templates/chat/.agents/skills/frontend-design/SKILL.md +5 -0
- package/src/templates/default/.agents/skills/delegate-to-agent/SKILL.md +28 -0
- package/src/templates/default/.agents/skills/frontend-design/SKILL.md +5 -0
- package/src/templates/workspace-core/.agents/skills/authentication/SKILL.md +24 -1
- package/src/templates/workspace-core/.agents/skills/delegate-to-agent/SKILL.md +28 -0
- package/src/templates/workspace-core/.agents/skills/extensions/SKILL.md +6 -2
- package/src/templates/workspace-core/.agents/skills/extensions/references/api.md +1 -1
- package/src/templates/workspace-core/.agents/skills/frontend-design/SKILL.md +5 -0
- package/src/templates/workspace-core/.agents/skills/generative-ui/SKILL.md +3 -1
|
@@ -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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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;
|
package/dist/secrets/routes.d.ts
CHANGED
|
@@ -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 =
|
|
955
|
-
|
|
956
|
-
|
|
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 "";
|
package/dist/server/auth.js
CHANGED
|
@@ -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
|
-
|
|
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.
|
|
1697
|
-
//
|
|
1698
|
-
//
|
|
1699
|
-
//
|
|
1700
|
-
|
|
1701
|
-
|
|
1702
|
-
|
|
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
|
|
3050
|
-
//
|
|
3051
|
-
//
|
|
3052
|
-
if (isSendVerificationEmail ||
|
|
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 =
|
|
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
|
|
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(
|
|
3311
|
+
if (isDesktopMagicLinkCallbackPath(callbackPath)) {
|
|
3290
3312
|
desktopFlow = await issueDesktopMagicLinkFlow();
|
|
3291
|
-
|
|
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:
|
|
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
|
-
?
|
|
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,
|
|
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.
|
|
3081
|
-
//
|
|
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
|
|
3087
|
-
//
|
|
3088
|
-
|
|
3089
|
-
|
|
3090
|
-
|
|
3091
|
-
|
|
3092
|
-
|
|
3093
|
-
|
|
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.
|
|
10
|
-
*
|
|
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 →
|
|
13
|
-
*
|
|
14
|
-
*
|
|
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.
|
|
72
|
-
*
|
|
73
|
-
*
|
|
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;
|