@agent-native/core 0.168.0 → 0.168.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/corpus/README.md +1 -1
- package/corpus/templates/analytics/netlify.toml +4 -4
- package/corpus/templates/assets/netlify.toml +4 -1
- package/corpus/templates/brain/netlify.toml +4 -1
- package/corpus/templates/calendar/netlify.toml +4 -1
- package/corpus/templates/chat/netlify.toml +4 -1
- package/corpus/templates/clips/desktop/src-tauri/src/util.rs +32 -0
- package/corpus/templates/clips/netlify.toml +4 -1
- package/corpus/templates/content/netlify.toml +4 -1
- package/corpus/templates/crm/netlify.toml +6 -1
- package/corpus/templates/design/netlify.toml +4 -1
- package/corpus/templates/dispatch/netlify.toml +4 -1
- package/corpus/templates/factory/netlify.toml +4 -1
- package/corpus/templates/forms/netlify.toml +4 -1
- package/corpus/templates/macros/netlify.toml +3 -3
- package/corpus/templates/mail/actions/view-screen.ts +80 -8
- package/corpus/templates/mail/app/components/email/EmailList.tsx +3 -1
- package/corpus/templates/mail/app/components/email/EmailListItem.tsx +1 -35
- package/corpus/templates/mail/app/components/email/EmailThread.tsx +16 -8
- package/corpus/templates/mail/app/components/layout/AppLayout.tsx +146 -87
- package/corpus/templates/mail/app/global.css +21 -0
- package/corpus/templates/mail/app/hooks/use-emails.ts +6 -0
- package/corpus/templates/mail/app/hooks/use-navigation-state.ts +2 -0
- package/corpus/templates/mail/app/lib/inbox-tabs.ts +5 -0
- package/corpus/templates/mail/app/lib/label-colors.ts +47 -0
- package/corpus/templates/mail/app/pages/InboxPage.tsx +25 -8
- package/corpus/templates/mail/netlify.toml +4 -1
- package/corpus/templates/mail/server/handlers/emails.ts +27 -2
- package/corpus/templates/plan/netlify.toml +4 -1
- package/corpus/templates/slides/netlify.toml +4 -1
- package/corpus/templates/tasks/netlify.toml +6 -1
- package/dist/app-config/migration.d.ts +5 -0
- package/dist/app-config/migration.js +11 -0
- package/dist/app-config/schema.d.ts +4 -0
- package/dist/app-config/schema.js +2 -0
- package/dist/client/AgentPanel.d.ts +3 -1
- package/dist/client/AgentPanel.js +2 -2
- package/dist/client/agent-page/AgentTabsPage.d.ts +4 -1
- package/dist/client/agent-page/AgentTabsPage.js +2 -2
- package/dist/client/integrations/IntegrationConnectionChoice.d.ts +4 -1
- package/dist/client/integrations/IntegrationConnectionChoice.js +6 -2
- package/dist/client/onboarding/FirstRunOnboarding.js +9 -5
- package/dist/client/resources/McpIntegrationDialog.d.ts +3 -1
- package/dist/client/resources/McpIntegrationDialog.js +181 -112
- package/dist/client/resources/mcp-integration-catalog.d.ts +1 -0
- package/dist/client/resources/mcp-integration-catalog.js +5 -2
- package/dist/collab/routes.d.ts +1 -1
- package/dist/db/migrations.js +10 -2
- package/dist/deploy/build.js +6 -0
- package/dist/deploy/netlify-static-headers.d.ts +3 -0
- package/dist/deploy/netlify-static-headers.js +60 -0
- package/dist/file-upload/actions/upload-image.d.ts +1 -1
- package/dist/localization/default-messages.d.ts +9 -0
- package/dist/localization/default-messages.js +9 -0
- package/dist/observability/routes.d.ts +6 -6
- package/dist/provider-api/actions/custom-provider-registration.d.ts +16 -16
- package/dist/provider-api/actions/provider-api.d.ts +17 -17
- package/dist/resources/handlers.d.ts +2 -2
- package/dist/server/transcribe-voice.d.ts +1 -1
- package/dist/templates/chat/netlify.toml +4 -1
- package/dist/vite/client.js +2 -0
- package/package.json +2 -1
- package/src/templates/chat/netlify.toml +4 -1
|
@@ -1743,10 +1743,13 @@ export const listLabels = defineEventHandler(async (_event: H3Event) => {
|
|
|
1743
1743
|
totalCount: number;
|
|
1744
1744
|
}
|
|
1745
1745
|
>();
|
|
1746
|
+
let successfulAccountReads = 0;
|
|
1747
|
+
let failedAccountReads = 0;
|
|
1746
1748
|
// Fetch labels from each account sequentially to avoid race conditions on the shared map
|
|
1747
1749
|
for (const { accessToken } of accountTokens) {
|
|
1748
1750
|
try {
|
|
1749
1751
|
const res = await gmailListLabels(accessToken);
|
|
1752
|
+
successfulAccountReads += 1;
|
|
1750
1753
|
for (const label of res.labels || []) {
|
|
1751
1754
|
if (!label.id || !label.name) continue;
|
|
1752
1755
|
const gmailId = label.id;
|
|
@@ -1791,7 +1794,25 @@ export const listLabels = defineEventHandler(async (_event: H3Event) => {
|
|
|
1791
1794
|
});
|
|
1792
1795
|
}
|
|
1793
1796
|
}
|
|
1794
|
-
} catch {
|
|
1797
|
+
} catch {
|
|
1798
|
+
// A partial label map is not safe to return because it drops labels
|
|
1799
|
+
// from accounts that failed and makes counts look authoritative.
|
|
1800
|
+
failedAccountReads += 1;
|
|
1801
|
+
}
|
|
1802
|
+
}
|
|
1803
|
+
if (failedAccountReads > 0) {
|
|
1804
|
+
console.warn(
|
|
1805
|
+
`[listLabels] ${failedAccountReads} Gmail account label read(s) failed`,
|
|
1806
|
+
);
|
|
1807
|
+
}
|
|
1808
|
+
if (
|
|
1809
|
+
accountTokens.length === 0 ||
|
|
1810
|
+
successfulAccountReads === 0 ||
|
|
1811
|
+
failedAccountReads > 0
|
|
1812
|
+
) {
|
|
1813
|
+
console.error("[listLabels] Gmail label fetch failed");
|
|
1814
|
+
setResponseStatus(_event, 502);
|
|
1815
|
+
return { error: "Unable to load Gmail labels. Please retry." };
|
|
1795
1816
|
}
|
|
1796
1817
|
const labels: Label[] = Array.from(labelMap.values());
|
|
1797
1818
|
|
|
@@ -1821,7 +1842,11 @@ export const listLabels = defineEventHandler(async (_event: H3Event) => {
|
|
|
1821
1842
|
}
|
|
1822
1843
|
|
|
1823
1844
|
return labels;
|
|
1824
|
-
} catch {
|
|
1845
|
+
} catch {
|
|
1846
|
+
console.error("[listLabels] Gmail label request failed");
|
|
1847
|
+
setResponseStatus(_event, 502);
|
|
1848
|
+
return { error: "Unable to load Gmail labels. Please retry." };
|
|
1849
|
+
}
|
|
1825
1850
|
}
|
|
1826
1851
|
return readLabels(email);
|
|
1827
1852
|
});
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[build]
|
|
2
2
|
ignore = "node ./scripts/netlify-ignore-build.mjs plan"
|
|
3
|
-
command = "export DATABASE_URL=${NETLIFY_DATABASE_URL:-$DATABASE_URL} && pnpm install && NITRO_PRESET=netlify pnpm --filter plan build && if [ \"${CONTEXT:-}\" = \"production\" ]; then pnpm --filter plan migrate:production; fi"
|
|
3
|
+
command = "export DATABASE_URL=${NETLIFY_DATABASE_URL:-$DATABASE_URL} && pnpm install && NITRO_PRESET=netlify pnpm --filter plan build && if [ \"${CONTEXT:-}\" = \"production\" ] || [ \"${AGENT_NATIVE_RUN_RELEASE_MIGRATIONS:-}\" = \"1\" ]; then pnpm --filter plan migrate:production; fi"
|
|
4
4
|
publish = "templates/plan/dist"
|
|
5
5
|
functions = "templates/plan/.netlify/functions-internal"
|
|
6
6
|
|
|
@@ -15,6 +15,9 @@ AGENT_CHAT_DURABLE_BACKGROUND = "true"
|
|
|
15
15
|
AGENT_NATIVE_HOSTED_HARNESS = "true"
|
|
16
16
|
AGENT_NATIVE_ENABLE_KEEP_WARM = "1"
|
|
17
17
|
AGENT_NATIVE_DISABLE_KEEP_WARM_BACKGROUND = "1"
|
|
18
|
+
# Production release migrations own schema setup; request functions must skip
|
|
19
|
+
# migration probes on every serverless invocation.
|
|
20
|
+
AGENT_NATIVE_RELEASE_MIGRATIONS = "1"
|
|
18
21
|
|
|
19
22
|
# A2A/MCP calls may include plan generation, artifact serialization, and
|
|
20
23
|
# feedback polling. Keep this aligned with other agent-heavy hosted templates.
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
ignore = "node ./scripts/netlify-ignore-build.mjs slides"
|
|
3
3
|
# Rebuild Core explicitly so a cached Netlify install cannot bundle an older
|
|
4
4
|
# agent loop or A2A handler into Slides' server functions.
|
|
5
|
-
command = "export DATABASE_URL=${NETLIFY_DATABASE_URL:-$DATABASE_URL} && pnpm install && pnpm --filter @agent-native/core build && NITRO_PRESET=netlify pnpm --filter slides build && if [ \"${CONTEXT:-}\" = \"production\" ]; then pnpm --filter slides migrate:production; fi"
|
|
5
|
+
command = "export DATABASE_URL=${NETLIFY_DATABASE_URL:-$DATABASE_URL} && pnpm install && pnpm --filter @agent-native/core build && NITRO_PRESET=netlify pnpm --filter slides build && if [ \"${CONTEXT:-}\" = \"production\" ] || [ \"${AGENT_NATIVE_RUN_RELEASE_MIGRATIONS:-}\" = \"1\" ]; then pnpm --filter slides migrate:production; fi"
|
|
6
6
|
publish = "templates/slides/dist"
|
|
7
7
|
functions = "templates/slides/.netlify/functions-internal"
|
|
8
8
|
|
|
@@ -18,6 +18,9 @@ AGENT_CHAT_DURABLE_BACKGROUND = "true"
|
|
|
18
18
|
AGENT_NATIVE_HOSTED_HARNESS = "true"
|
|
19
19
|
AGENT_NATIVE_ENABLE_KEEP_WARM = "1"
|
|
20
20
|
AGENT_NATIVE_DISABLE_KEEP_WARM_BACKGROUND = "1"
|
|
21
|
+
# Production release migrations own schema setup; request functions must skip
|
|
22
|
+
# migration probes on every serverless invocation.
|
|
23
|
+
AGENT_NATIVE_RELEASE_MIGRATIONS = "1"
|
|
21
24
|
|
|
22
25
|
# Function wall for the non-agent long-request paths (deck import/export,
|
|
23
26
|
# image generation). Agent chat opts into the separate Netlify background
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[build]
|
|
2
2
|
ignore = "node ./scripts/netlify-ignore-build.mjs tasks"
|
|
3
|
-
command = "export DATABASE_URL=${NETLIFY_DATABASE_URL:-$DATABASE_URL} && pnpm install && NITRO_PRESET=netlify pnpm --filter tasks build && if [ \"${CONTEXT:-}\" = \"production\" ]; then pnpm --filter tasks migrate:production; fi"
|
|
3
|
+
command = "export DATABASE_URL=${NETLIFY_DATABASE_URL:-$DATABASE_URL} && pnpm install && NITRO_PRESET=netlify pnpm --filter tasks build && if [ \"${CONTEXT:-}\" = \"production\" ] || [ \"${AGENT_NATIVE_RUN_RELEASE_MIGRATIONS:-}\" = \"1\" ]; then pnpm --filter tasks migrate:production; fi"
|
|
4
4
|
publish = "templates/tasks/dist"
|
|
5
5
|
functions = "templates/tasks/.netlify/functions-internal"
|
|
6
6
|
|
|
@@ -9,3 +9,8 @@ GA_MEASUREMENT_ID = "G-ESF7FYXGN9"
|
|
|
9
9
|
GTM_CONTAINER_ID = "GTM-N3WSTXZ"
|
|
10
10
|
NITRO_PRESET = "netlify"
|
|
11
11
|
NPM_CONFIG_PRODUCTION = "false"
|
|
12
|
+
|
|
13
|
+
[context.production.environment]
|
|
14
|
+
# Production release migrations own schema setup; request functions must skip
|
|
15
|
+
# migration probes on every serverless invocation.
|
|
16
|
+
AGENT_NATIVE_RELEASE_MIGRATIONS = "1"
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export const migrationConfig = z.object({
|
|
3
|
+
releaseMigrations: z.boolean().default(false).meta({
|
|
4
|
+
env: "AGENT_NATIVE_RELEASE_MIGRATIONS",
|
|
5
|
+
doc: "Treat database migrations as release-owned so request runtimes only probe an already-prepared schema.",
|
|
6
|
+
}),
|
|
7
|
+
betaSchemaOwner: z.string().trim().min(1).optional().meta({
|
|
8
|
+
env: "AGENT_NATIVE_BETA_SCHEMA_OWNER",
|
|
9
|
+
doc: "Schema owner marker embedded in a prebuilt beta server bundle.",
|
|
10
|
+
}),
|
|
11
|
+
});
|
|
@@ -40,6 +40,10 @@ export declare const appConfigSchema: z.ZodObject<{
|
|
|
40
40
|
integrations: z.ZodPrefault<z.ZodObject<{
|
|
41
41
|
allowUnverifiedWebhooks: z.ZodDefault<z.ZodBoolean>;
|
|
42
42
|
}, z.core.$strip>>;
|
|
43
|
+
migration: z.ZodPrefault<z.ZodObject<{
|
|
44
|
+
releaseMigrations: z.ZodDefault<z.ZodBoolean>;
|
|
45
|
+
betaSchemaOwner: z.ZodOptional<z.ZodString>;
|
|
46
|
+
}, z.core.$strip>>;
|
|
43
47
|
privateBlob: z.ZodPrefault<z.ZodObject<{
|
|
44
48
|
provider: z.ZodOptional<z.ZodString>;
|
|
45
49
|
publicUploadFallback: z.ZodDefault<z.ZodBoolean>;
|
|
@@ -4,6 +4,7 @@ import { agentConfig } from "./agent.js";
|
|
|
4
4
|
import { appConfig } from "./app.js";
|
|
5
5
|
import { authConfig } from "./auth.js";
|
|
6
6
|
import { integrationsConfig } from "./integrations.js";
|
|
7
|
+
import { migrationConfig } from "./migration.js";
|
|
7
8
|
import { privateBlobConfig } from "./private-blob.js";
|
|
8
9
|
import { workspaceConfig } from "./workspace.js";
|
|
9
10
|
/**
|
|
@@ -28,6 +29,7 @@ export const appConfigSchema = z.object({
|
|
|
28
29
|
app: appConfig.prefault({}),
|
|
29
30
|
auth: authConfig.prefault({}),
|
|
30
31
|
integrations: integrationsConfig.prefault({}),
|
|
32
|
+
migration: migrationConfig.prefault({}),
|
|
31
33
|
privateBlob: privateBlobConfig.prefault({}),
|
|
32
34
|
workspace: workspaceConfig.prefault({}),
|
|
33
35
|
});
|
|
@@ -187,6 +187,8 @@ export interface AgentSidebarProps {
|
|
|
187
187
|
onAgentChange?: AssistantChatProps["onAgentChange"];
|
|
188
188
|
/** Route local runtime setup through the host's native bridge. */
|
|
189
189
|
onConnectLocalRuntime?: AssistantChatProps["onConnectLocalRuntime"];
|
|
190
|
+
/** Route hosted provider setup through the host's native bridge. */
|
|
191
|
+
onConnectProvider?: AssistantChatProps["onConnectProvider"];
|
|
190
192
|
/** Bring-your-own runtime used by embedded hosts such as Electron. */
|
|
191
193
|
runtime?: AssistantChatProps["runtime"];
|
|
192
194
|
/** Explicit key for recreating an injected runtime adapter. */
|
|
@@ -258,7 +260,7 @@ export interface AgentSidebarProps {
|
|
|
258
260
|
* Wraps app content with a toggleable agent sidebar.
|
|
259
261
|
* Use AgentToggleButton in your header to open/close it.
|
|
260
262
|
*/
|
|
261
|
-
export declare function AgentSidebar({ children, emptyStateText, suggestions, dynamicSuggestions, composerToolbarSlot, composerSlot, onComposerTextChange, imageModelMenu, availableAgents, availableModels, modelListLoading, selectedAgent, onAgentChange, onConnectLocalRuntime, runtime, adapterReloadKey, threadFooterSlot, defaultSidebarWidth, sidebarWidth, position, defaultOpen, animateMobile, animateDesktop, chatViewTransition, chatViewTransitionHandoff, storageKey, openStorageKey, apiUrl, agentChatSurface, desktopIdentityUnauthenticated, desktopIdentityAuthenticated, showTabBar, suppressInlineOpenApp, composerPlaceholder, openOnChatRunning, onFullscreenRequest, scope, isolateHistoryByScope, showScopeBadge, browserTabId, threadUrlSync, agentPageHref, suppressFirstRunOnboarding, }: AgentSidebarProps): React.JSX.Element;
|
|
263
|
+
export declare function AgentSidebar({ children, emptyStateText, suggestions, dynamicSuggestions, composerToolbarSlot, composerSlot, onComposerTextChange, imageModelMenu, availableAgents, availableModels, modelListLoading, selectedAgent, onAgentChange, onConnectLocalRuntime, onConnectProvider, runtime, adapterReloadKey, threadFooterSlot, defaultSidebarWidth, sidebarWidth, position, defaultOpen, animateMobile, animateDesktop, chatViewTransition, chatViewTransitionHandoff, storageKey, openStorageKey, apiUrl, agentChatSurface, desktopIdentityUnauthenticated, desktopIdentityAuthenticated, showTabBar, suppressInlineOpenApp, composerPlaceholder, openOnChatRunning, onFullscreenRequest, scope, isolateHistoryByScope, showScopeBadge, browserTabId, threadUrlSync, agentPageHref, suppressFirstRunOnboarding, }: AgentSidebarProps): React.JSX.Element;
|
|
262
264
|
/**
|
|
263
265
|
* Focus the agent chat composer input.
|
|
264
266
|
* Opens the sidebar if closed, then focuses the text input.
|
|
@@ -1418,7 +1418,7 @@ export function AgentChatSurface({ mode = "panel", className, defaultMode = "cha
|
|
|
1418
1418
|
* Wraps app content with a toggleable agent sidebar.
|
|
1419
1419
|
* Use AgentToggleButton in your header to open/close it.
|
|
1420
1420
|
*/
|
|
1421
|
-
export function AgentSidebar({ children, emptyStateText = "How can I help you?", suggestions, dynamicSuggestions, composerToolbarSlot, composerSlot, onComposerTextChange, imageModelMenu, availableAgents, availableModels, modelListLoading, selectedAgent, onAgentChange, onConnectLocalRuntime, runtime, adapterReloadKey, threadFooterSlot, defaultSidebarWidth, sidebarWidth, position = "right", defaultOpen = false, animateMobile = true, animateDesktop = true, chatViewTransition = false, chatViewTransitionHandoff = false, storageKey, openStorageKey, apiUrl, agentChatSurface, desktopIdentityUnauthenticated, desktopIdentityAuthenticated, showTabBar = true, suppressInlineOpenApp, composerPlaceholder, openOnChatRunning = false, onFullscreenRequest, scope, isolateHistoryByScope = false, showScopeBadge, browserTabId, threadUrlSync, agentPageHref, suppressFirstRunOnboarding = false, }) {
|
|
1421
|
+
export function AgentSidebar({ children, emptyStateText = "How can I help you?", suggestions, dynamicSuggestions, composerToolbarSlot, composerSlot, onComposerTextChange, imageModelMenu, availableAgents, availableModels, modelListLoading, selectedAgent, onAgentChange, onConnectLocalRuntime, onConnectProvider, runtime, adapterReloadKey, threadFooterSlot, defaultSidebarWidth, sidebarWidth, position = "right", defaultOpen = false, animateMobile = true, animateDesktop = true, chatViewTransition = false, chatViewTransitionHandoff = false, storageKey, openStorageKey, apiUrl, agentChatSurface, desktopIdentityUnauthenticated, desktopIdentityAuthenticated, showTabBar = true, suppressInlineOpenApp, composerPlaceholder, openOnChatRunning = false, onFullscreenRequest, scope, isolateHistoryByScope = false, showScopeBadge, browserTabId, threadUrlSync, agentPageHref, suppressFirstRunOnboarding = false, }) {
|
|
1422
1422
|
const staticHostedHarnessEnabled = isHostedHarnessConfigured(injectedAgentNativeConfig().harness);
|
|
1423
1423
|
const hostedHarnessQuery = useActionQuery("get-hosted-harness-config", undefined, { enabled: staticHostedHarnessEnabled });
|
|
1424
1424
|
const hostedHarnessStatus = hostedHarnessQuery.data;
|
|
@@ -2059,7 +2059,7 @@ export function AgentSidebar({ children, emptyStateText = "How can I help you?",
|
|
|
2059
2059
|
? "desktop"
|
|
2060
2060
|
: undefined, "data-agent-sidebar-layout": panelLayout, "data-agent-sidebar-position": effectivePosition, "data-agent-native-hosted-harness-ui": hostedHarnessUi ? "desktop" : undefined, "data-agent-sidebar-state": panelOpen ? "open" : "closed", "data-agent-sidebar-per-app-chat": isPerAppChatSidebar ? "true" : undefined, "data-agent-sidebar-resizing": isResizing ? "true" : undefined, "data-agent-sidebar-chat-handoff": chatViewTransitionHandoff ? "true" : undefined, style: chatViewTransition
|
|
2061
2061
|
? getAgentChatViewTransitionStyle(panelStyle)
|
|
2062
|
-
: panelStyle, inert: sidebarAnimationEnabled && !panelOpen ? true : undefined, "aria-hidden": sidebarAnimationEnabled && !panelOpen ? true : undefined, children: _jsx("div", { className: "agent-sidebar-panel-inner flex min-h-0 flex-1 flex-col", children: _jsx(AgentPanel, { emptyStateText: emptyStateText, suggestions: suggestions, dynamicSuggestions: dynamicSuggestions, composerToolbarSlot: composerToolbarSlot, composerSlot: composerSlot, onComposerTextChange: onComposerTextChange, imageModelMenu: imageModelMenu, availableAgents: effectiveAvailableAgents, availableModels: availableModels, modelListLoading: modelListLoading, selectedAgent: effectiveSelectedAgent, onAgentChange: effectiveOnAgentChange, hostedHarness: hostedHarnessEnabled, onConnectLocalRuntime: onConnectLocalRuntime, runtime: runtime, adapterReloadKey: adapterReloadKey, threadFooterSlot: threadFooterSlot, apiUrl: apiUrl, agentChatSurface: agentChatSurface, desktopIdentityUnauthenticated: desktopIdentityUnauthenticated, desktopIdentityAuthenticated: desktopIdentityAuthenticated, showTabBar: effectiveShowTabBar, suppressInlineOpenApp: suppressInlineOpenApp, composerPlaceholder: composerPlaceholder, missingApiKeySetupLayout: "sidebar", onCollapse: () => setOpenPersisted(false), onSnapTo75Percent: isMobile ? undefined : snapTo75Percent, isWideDrawer: isMobile ? false : isWideDrawer, onExitWideDrawer: isMobile ? undefined : exitWideDrawer, onFullViewRequest: onFullscreenRequest, storageKey: storageKey, scope: scope, isolateHistoryByScope: isolateHistoryByScope, showScopeBadge: showScopeBadge, browserTabId: browserTabId, threadUrlSync: threadUrlSync, agentPageHref: agentPageHref, allowSettingsMode: false, chatOnly: true }) }) }), showResizeHandle && isLeft && (_jsx(ResizeHandle, { position: effectivePosition, onDrag: handleDrag, onResizeStart: handleResizeStart, onResizeEnd: handleResizeEnd }))] })) : null;
|
|
2062
|
+
: panelStyle, inert: sidebarAnimationEnabled && !panelOpen ? true : undefined, "aria-hidden": sidebarAnimationEnabled && !panelOpen ? true : undefined, children: _jsx("div", { className: "agent-sidebar-panel-inner flex min-h-0 flex-1 flex-col", children: _jsx(AgentPanel, { emptyStateText: emptyStateText, suggestions: suggestions, dynamicSuggestions: dynamicSuggestions, composerToolbarSlot: composerToolbarSlot, composerSlot: composerSlot, onComposerTextChange: onComposerTextChange, imageModelMenu: imageModelMenu, availableAgents: effectiveAvailableAgents, availableModels: availableModels, modelListLoading: modelListLoading, selectedAgent: effectiveSelectedAgent, onAgentChange: effectiveOnAgentChange, hostedHarness: hostedHarnessEnabled, onConnectProvider: onConnectProvider, onConnectLocalRuntime: onConnectLocalRuntime, runtime: runtime, adapterReloadKey: adapterReloadKey, threadFooterSlot: threadFooterSlot, apiUrl: apiUrl, agentChatSurface: agentChatSurface, desktopIdentityUnauthenticated: desktopIdentityUnauthenticated, desktopIdentityAuthenticated: desktopIdentityAuthenticated, showTabBar: effectiveShowTabBar, suppressInlineOpenApp: suppressInlineOpenApp, composerPlaceholder: composerPlaceholder, missingApiKeySetupLayout: "sidebar", onCollapse: () => setOpenPersisted(false), onSnapTo75Percent: isMobile ? undefined : snapTo75Percent, isWideDrawer: isMobile ? false : isWideDrawer, onExitWideDrawer: isMobile ? undefined : exitWideDrawer, onFullViewRequest: onFullscreenRequest, storageKey: storageKey, scope: scope, isolateHistoryByScope: isolateHistoryByScope, showScopeBadge: showScopeBadge, browserTabId: browserTabId, threadUrlSync: threadUrlSync, agentPageHref: agentPageHref, allowSettingsMode: false, chatOnly: true }) }) }), showResizeHandle && isLeft && (_jsx(ResizeHandle, { position: effectivePosition, onDrag: handleDrag, onResizeStart: handleResizeStart, onResizeEnd: handleResizeEnd }))] })) : null;
|
|
2063
2063
|
const drawerPlaceholder = wideDrawerEnabled && !presentationMode && panelOpen ? (_jsx("div", { "aria-hidden": "true", className: "agent-sidebar-drawer-placeholder shrink-0", "data-agent-sidebar-placeholder": "true", style: { width: drawerPlaceholderWidth + 1 } })) : null;
|
|
2064
2064
|
return (_jsx(AgentSidebarOnboardingContext.Provider, { value: true, children: _jsxs(RealtimeVoiceModeProvider, { browserTabId: browserTabId, children: [showFirstRunOnboarding && (_jsx(Suspense, { fallback: null, children: _jsx(FirstRunOnboarding, {}) })), _jsxs("div", { className: "agent-sidebar-shell flex min-w-0 flex-1 h-screen overflow-hidden", "data-agent-sidebar-position": effectivePosition, "data-agent-native-hosted-harness-ui": hostedHarnessUi ? "desktop" : undefined, "data-agent-native-hosted-chat": isPerAppChatHosted ? "true" : undefined, "data-agent-sidebar-resizing": isResizing ? "true" : undefined, children: [isMobile &&
|
|
2065
2065
|
!isPerAppChatHosted &&
|
|
@@ -3,7 +3,10 @@ import type { ResourceView } from "../resources/ResourcesPanel.js";
|
|
|
3
3
|
import type { SettingsTabItem } from "../settings/SettingsTabsPage.js";
|
|
4
4
|
import type { AgentPageTabProps } from "./types.js";
|
|
5
5
|
export declare const AGENT_RESOURCE_DOCS_HREF: Record<ResourceView, string>;
|
|
6
|
-
export declare function ConnectionsTab({ canManageOrg, }?: Partial<AgentPageTabProps>
|
|
6
|
+
export declare function ConnectionsTab({ canManageOrg, onOAuthStart, oauthReturnPath, }?: Partial<AgentPageTabProps> & {
|
|
7
|
+
onOAuthStart?: (url: string) => void | Promise<void>;
|
|
8
|
+
oauthReturnPath?: string;
|
|
9
|
+
}): import("react").JSX.Element;
|
|
7
10
|
export declare const AGENT_ACCESS_DOCS_HREF: {
|
|
8
11
|
readonly mcp: string;
|
|
9
12
|
readonly a2a: string;
|
|
@@ -117,7 +117,7 @@ function ServerStatus({ server }) {
|
|
|
117
117
|
}
|
|
118
118
|
return (_jsx("span", { className: "text-[11px] text-muted-foreground", children: "Status unknown" }));
|
|
119
119
|
}
|
|
120
|
-
export function ConnectionsTab({ canManageOrg, } = {}) {
|
|
120
|
+
export function ConnectionsTab({ canManageOrg, onOAuthStart, oauthReturnPath, } = {}) {
|
|
121
121
|
const t = useT();
|
|
122
122
|
const serversQuery = useMcpServers();
|
|
123
123
|
const createServer = useCreateMcpServer();
|
|
@@ -181,7 +181,7 @@ export function ConnectionsTab({ canManageOrg, } = {}) {
|
|
|
181
181
|
? "No personal agent integrations yet"
|
|
182
182
|
: "No workspace-shared agent integrations yet", description: section.scope === "user"
|
|
183
183
|
? "Connect a service to give the agent access to it."
|
|
184
|
-
: "Agent integrations shared with this workspace will appear here." }))] }, section.scope))) })), _jsx(McpIntegrationDialog, { open: dialogOpen, onOpenChange: setDialogOpen, defaultScope: "user", canCreateOrgMcp: canCreateOrgMcp, hasOrg: hasOrg, onCreateMcpServer: onCreateMcpServer })] }) }));
|
|
184
|
+
: "Agent integrations shared with this workspace will appear here." }))] }, section.scope))) })), _jsx(McpIntegrationDialog, { open: dialogOpen, onOpenChange: setDialogOpen, defaultScope: "user", canCreateOrgMcp: canCreateOrgMcp, hasOrg: hasOrg, onCreateMcpServer: onCreateMcpServer, onOAuthStart: onOAuthStart, oauthReturnPath: oauthReturnPath })] }) }));
|
|
185
185
|
}
|
|
186
186
|
export const AGENT_ACCESS_DOCS_HREF = {
|
|
187
187
|
mcp: docsUrl("mcp-protocol"),
|
|
@@ -3,9 +3,12 @@ export interface IntegrationConnectionChoiceProps {
|
|
|
3
3
|
name: string;
|
|
4
4
|
logo?: ReactNode;
|
|
5
5
|
showWorkspaceOption: boolean;
|
|
6
|
+
workspaceOptionDisabled?: boolean;
|
|
7
|
+
workspaceOptionDisabledReason?: string;
|
|
8
|
+
personalOnlyReason?: string;
|
|
6
9
|
busy?: boolean;
|
|
7
10
|
onPersonal: () => void;
|
|
8
11
|
onWorkspace: () => void;
|
|
9
12
|
}
|
|
10
13
|
/** The one small decision before an integration's advanced setup surface. */
|
|
11
|
-
export declare function IntegrationConnectionChoice({ name, logo, showWorkspaceOption, busy, onPersonal, onWorkspace, }: IntegrationConnectionChoiceProps): import("react").JSX.Element;
|
|
14
|
+
export declare function IntegrationConnectionChoice({ name, logo, showWorkspaceOption, workspaceOptionDisabled, workspaceOptionDisabledReason, personalOnlyReason, busy, onPersonal, onWorkspace, }: IntegrationConnectionChoiceProps): import("react").JSX.Element;
|
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { IconLoader2, IconUser, IconUsersGroup } from "@tabler/icons-react";
|
|
3
|
+
import { useT } from "../i18n.js";
|
|
3
4
|
/** The one small decision before an integration's advanced setup surface. */
|
|
4
|
-
export function IntegrationConnectionChoice({ name, logo, showWorkspaceOption, busy = false, onPersonal, onWorkspace, }) {
|
|
5
|
-
|
|
5
|
+
export function IntegrationConnectionChoice({ name, logo, showWorkspaceOption, workspaceOptionDisabled = false, workspaceOptionDisabledReason, personalOnlyReason, busy = false, onPersonal, onWorkspace, }) {
|
|
6
|
+
const t = useT();
|
|
7
|
+
return (_jsxs("div", { className: "flex min-h-full flex-1 flex-col bg-background", children: [_jsx("header", { className: "flex min-h-16 items-center border-b border-border px-6 sm:px-10", children: _jsxs("div", { className: "flex min-w-0 items-center gap-3", children: [logo ? (_jsx("span", { className: "flex size-8 shrink-0 items-center justify-center rounded-md bg-muted/50 text-foreground", children: logo })) : null, _jsxs("span", { className: "truncate text-sm font-medium text-foreground", children: [t("mcpIntegrations.connect"), " ", name] })] }) }), _jsx("main", { className: "flex flex-1 justify-center overflow-y-auto px-6 py-12 sm:px-10 sm:py-[12vh]", children: _jsxs("div", { className: "w-full max-w-[420px] self-start", children: [_jsx("h1", { className: "text-2xl font-semibold tracking-[-0.03em] text-foreground sm:text-[28px]", children: t("mcpIntegrations.scopeChoiceTitle") }), _jsx("p", { className: "mt-2 text-sm leading-6 text-muted-foreground", children: t("mcpIntegrations.scopeChoiceDescription") }), _jsxs("div", { className: "mt-8 grid gap-2.5", children: [_jsxs("button", { type: "button", onClick: onPersonal, disabled: busy, "aria-busy": busy, className: "flex min-h-12 items-center gap-3 rounded-lg bg-primary px-4 py-3 text-left text-primary-foreground transition-[background-color,opacity] hover:bg-primary/90 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background disabled:cursor-wait disabled:opacity-60", children: [_jsx(IconUser, { className: "size-4 shrink-0 opacity-75" }), _jsx("span", { className: "min-w-0 flex-1 text-sm font-medium", children: t("mcpIntegrations.connectForMe") }), busy ? (_jsx(IconLoader2, { className: "size-4 shrink-0 animate-spin" })) : null] }), showWorkspaceOption ? (_jsxs("button", { type: "button", onClick: onWorkspace, disabled: busy || workspaceOptionDisabled, "aria-describedby": workspaceOptionDisabledReason
|
|
8
|
+
? "integration-workspace-scope-restriction"
|
|
9
|
+
: undefined, className: "flex min-h-12 items-center gap-3 rounded-lg bg-muted/50 px-4 py-3 text-left text-foreground transition-colors hover:bg-muted/70 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background disabled:cursor-not-allowed disabled:opacity-60", children: [_jsx(IconUsersGroup, { className: "size-4 shrink-0 text-muted-foreground" }), _jsx("span", { className: "min-w-0 flex-1 text-sm font-medium", children: t("mcpIntegrations.setUpForWorkspace") }), workspaceOptionDisabledReason ? (_jsx("span", { id: "integration-workspace-scope-restriction", className: "shrink-0 text-[11px] font-normal text-muted-foreground", children: workspaceOptionDisabledReason })) : null] })) : null] }), personalOnlyReason ? (_jsx("p", { className: "mt-3 text-[11px] leading-relaxed text-muted-foreground", children: personalOnlyReason })) : null] }) })] }));
|
|
6
10
|
}
|
|
@@ -6,10 +6,10 @@ import { docsUrl } from "../../shared/docs-url.js";
|
|
|
6
6
|
import { appPath } from "../api-path.js";
|
|
7
7
|
import { Tooltip, TooltipContent, TooltipTrigger, } from "../components/ui/tooltip.js";
|
|
8
8
|
import { IntegrationGrid } from "../integrations/IntegrationGrid.js";
|
|
9
|
-
import { buildMcpOAuthStartUrl, filterMcpIntegrations, getDefaultMcpIntegrations, navigateToMcpOAuthStart,
|
|
9
|
+
import { buildMcpOAuthStartUrl, filterMcpIntegrations, getDefaultMcpIntegrations, navigateToMcpOAuthStart, } from "../resources/mcp-integration-catalog.js";
|
|
10
10
|
import { McpIntegrationDialog } from "../resources/McpIntegrationDialog.js";
|
|
11
11
|
import { McpIntegrationLogo } from "../resources/McpIntegrationLogo.js";
|
|
12
|
-
import { formatMcpServerError, useCreateMcpServer, useMcpServers, } from "../resources/use-mcp-servers.js";
|
|
12
|
+
import { formatMcpServerError, formatMcpServersLoadError, useCreateMcpServer, useMcpServers, } from "../resources/use-mcp-servers.js";
|
|
13
13
|
import { useBuilderConnectFlow } from "../settings/useBuilderStatus.js";
|
|
14
14
|
import { cn } from "../utils.js";
|
|
15
15
|
import { shouldSkipFirstRunIntegrations } from "./first-run-enabled.js";
|
|
@@ -122,7 +122,9 @@ export function FirstRunOnboarding({ skipIntegrations = shouldSkipFirstRunIntegr
|
|
|
122
122
|
connectingIntegrationId === integration.id) {
|
|
123
123
|
return;
|
|
124
124
|
}
|
|
125
|
-
if (
|
|
125
|
+
if (!mcpServersQuery.isSuccess)
|
|
126
|
+
return;
|
|
127
|
+
if (hasOrg) {
|
|
126
128
|
setIntegrationDialogId(integration.id);
|
|
127
129
|
return;
|
|
128
130
|
}
|
|
@@ -190,7 +192,7 @@ export function FirstRunOnboarding({ skipIntegrations = shouldSkipFirstRunIntegr
|
|
|
190
192
|
return (_jsx(OnboardingShell, { profile: profile, screen: "choice", children: _jsxs("div", { className: "mx-auto flex w-full max-w-xl flex-col gap-4", children: [_jsxs("div", { children: [_jsx("button", { type: "button", className: "mb-4 text-xs text-muted-foreground hover:text-foreground", onClick: () => setScreen("choice"), children: "Back" }), _jsx("h1", { className: "text-xl font-semibold tracking-[-0.04em] sm:text-2xl", children: "Your keys" })] }), _jsxs("div", { className: "rounded-xl bg-muted/35 p-4", children: [_jsx(CapabilityList, { capabilities: profile.capabilities }), _jsxs("div", { className: "mt-5 flex flex-col-reverse gap-2 pt-4 sm:flex-row sm:justify-between", children: [_jsx("button", { type: "button", className: secondaryButtonClass, onClick: () => setScreen("choice"), children: "Back" }), _jsxs("button", { type: "button", className: primaryButtonClass, onClick: handleOpenSettings, children: ["Open key settings", _jsx(IconArrowRight, { size: 15 })] }), _jsx("button", { type: "button", className: secondaryButtonClass, onClick: () => setScreen(skipIntegrations ? "ready" : "tools"), children: skipIntegrations ? "Continue" : "Continue to tools" })] })] })] }) }));
|
|
191
193
|
}
|
|
192
194
|
if (screen === "tools") {
|
|
193
|
-
return (_jsxs(OnboardingShell, { profile: profile, screen: "tools", footer: _jsxs("div", { "data-testid": "onboarding-tools-footer", className: "mx-auto flex w-full max-w-3xl flex-wrap items-center justify-end gap-2", children: [_jsx("button", { type: "button", className: secondaryButtonClass, onClick: handleFinish, children: "Skip for now" }), _jsxs("button", { type: "button", className: primaryButtonClass, onClick: handleFinish, children: ["Continue", _jsx(IconArrowRight, { size: 15 })] })] }), children: [_jsxs("div", { className: "mx-auto flex w-full max-w-4xl flex-col gap-5", children: [_jsxs("div", { children: [_jsx("h1", { className: "text-2xl font-semibold tracking-[-0.05em] sm:text-3xl", children: "This app is an agent." }), _jsx("p", { className: "mt-1.5 max-w-2xl text-sm leading-6 text-muted-foreground", children: "Connect the tools your agent can use to gather context and take action. You can add more later in Settings." })] }), _jsxs("div", { className: "flex flex-col gap-4", children: [_jsxs("div", { className: "flex flex-col gap-3 pb-4", children: [_jsxs("div", { className: "flex items-center justify-between gap-3", children: [_jsx("div", { children: _jsx("p", { className: "text-sm font-medium text-foreground", children: "Agent integrations" }) }), _jsxs("label", { className: "relative w-full max-w-xs", children: [_jsx(IconSearch, { className: "pointer-events-none absolute start-3 top-1/2 h-3.5 w-3.5 -translate-y-1/2 text-muted-foreground" }), _jsx("input", { value: integrationQuery, onChange: (event) => setIntegrationQuery(event.target.value), className: "h-9 w-full rounded-md border border-border bg-background pe-3 ps-8 text-[13px] text-foreground outline-none placeholder:text-muted-foreground/50 focus:ring-1 focus:ring-ring", placeholder: "Search integrations", "aria-label": "Search integrations" })] })] }), connectError && (_jsx("p", { className: "text-xs leading-5 text-destructive", children: connectError }))] }), _jsx(IntegrationGrid, { items: mcpIntegrations.map((integration) => {
|
|
195
|
+
return (_jsxs(OnboardingShell, { profile: profile, screen: "tools", footer: _jsxs("div", { "data-testid": "onboarding-tools-footer", className: "mx-auto flex w-full max-w-3xl flex-wrap items-center justify-end gap-2", children: [_jsx("button", { type: "button", className: secondaryButtonClass, onClick: handleFinish, children: "Skip for now" }), _jsxs("button", { type: "button", className: primaryButtonClass, onClick: handleFinish, children: ["Continue", _jsx(IconArrowRight, { size: 15 })] })] }), children: [_jsxs("div", { className: "mx-auto flex w-full max-w-4xl flex-col gap-5", children: [_jsxs("div", { children: [_jsx("h1", { className: "text-2xl font-semibold tracking-[-0.05em] sm:text-3xl", children: "This app is an agent." }), _jsx("p", { className: "mt-1.5 max-w-2xl text-sm leading-6 text-muted-foreground", children: "Connect the tools your agent can use to gather context and take action. You can add more later in Settings." })] }), _jsxs("div", { className: "flex flex-col gap-4", children: [_jsxs("div", { className: "flex flex-col gap-3 pb-4", children: [_jsxs("div", { className: "flex items-center justify-between gap-3", children: [_jsx("div", { children: _jsx("p", { className: "text-sm font-medium text-foreground", children: "Agent integrations" }) }), _jsxs("label", { className: "relative w-full max-w-xs", children: [_jsx(IconSearch, { className: "pointer-events-none absolute start-3 top-1/2 h-3.5 w-3.5 -translate-y-1/2 text-muted-foreground" }), _jsx("input", { value: integrationQuery, onChange: (event) => setIntegrationQuery(event.target.value), className: "h-9 w-full rounded-md border border-border bg-background pe-3 ps-8 text-[13px] text-foreground outline-none placeholder:text-muted-foreground/50 focus:ring-1 focus:ring-ring", placeholder: "Search integrations", "aria-label": "Search integrations" })] })] }), connectError && (_jsx("p", { className: "text-xs leading-5 text-destructive", children: connectError })), mcpServersQuery.isError ? (_jsxs("div", { role: "alert", className: "rounded-md border border-destructive/20 bg-destructive/5 px-3 py-2 text-xs text-destructive", children: [_jsx("p", { children: formatMcpServersLoadError(mcpServersQuery.error) }), _jsx("button", { type: "button", onClick: () => void mcpServersQuery.refetch(), disabled: mcpServersQuery.isFetching, className: "mt-2 font-medium underline underline-offset-2 hover:text-foreground disabled:cursor-wait disabled:opacity-60", children: mcpServersQuery.isFetching ? "Retrying…" : "Retry" })] })) : null] }), _jsx(IntegrationGrid, { items: mcpIntegrations.map((integration) => {
|
|
194
196
|
const connected = connectedUrls.has(compareUrl(integration.url));
|
|
195
197
|
return {
|
|
196
198
|
id: integration.id,
|
|
@@ -200,7 +202,9 @@ export function FirstRunOnboarding({ skipIntegrations = shouldSkipFirstRunIntegr
|
|
|
200
202
|
status: connected ? "Connected" : undefined,
|
|
201
203
|
statusClassName: "text-emerald-600 dark:text-emerald-400",
|
|
202
204
|
actionLabel: connected ? "Connected" : "Connect",
|
|
203
|
-
disabled: connected ||
|
|
205
|
+
disabled: connected ||
|
|
206
|
+
connectingIntegrationId === integration.id ||
|
|
207
|
+
!mcpServersQuery.isSuccess,
|
|
204
208
|
onAction: () => void connectIntegration(integration),
|
|
205
209
|
};
|
|
206
210
|
}), emptyLabel: "No integrations match." })] })] }), integrationDialogId && (_jsx(McpIntegrationDialog, { open: true, onOpenChange: (open) => {
|
|
@@ -10,7 +10,9 @@ export interface McpIntegrationDialogProps {
|
|
|
10
10
|
canCreateOrgMcp: boolean;
|
|
11
11
|
hasOrg: boolean;
|
|
12
12
|
onCreateMcpServer: (args: CreateMcpServerArgs) => Promise<unknown>;
|
|
13
|
+
onOAuthStart?: (url: string) => void | Promise<void>;
|
|
14
|
+
oauthReturnPath?: string;
|
|
13
15
|
onCreated?: () => void;
|
|
14
16
|
integrations?: DefaultMcpIntegration[];
|
|
15
17
|
}
|
|
16
|
-
export declare function McpIntegrationDialog({ open, onOpenChange, initialIntegrationId, connectIntegrationId, quickConnectIntegrationId, defaultScope, canCreateOrgMcp, hasOrg, onCreateMcpServer, onCreated, integrations, }: McpIntegrationDialogProps): import("react").JSX.Element | null;
|
|
18
|
+
export declare function McpIntegrationDialog({ open, onOpenChange, initialIntegrationId, connectIntegrationId, quickConnectIntegrationId, defaultScope, canCreateOrgMcp, hasOrg, onCreateMcpServer, onOAuthStart, oauthReturnPath, onCreated, integrations, }: McpIntegrationDialogProps): import("react").JSX.Element | null;
|