@agent-native/core 0.157.6 → 0.157.8
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/agent-native.config.ts +5 -0
- package/corpus/templates/analytics/netlify.toml +1 -0
- package/corpus/templates/analytics/server/lib/first-party-analytics-backend.ts +23 -5
- package/corpus/templates/analytics/server/plugins/agent-chat.ts +4 -0
- package/corpus/templates/assets/netlify.toml +3 -0
- package/corpus/templates/brain/netlify.toml +3 -0
- package/corpus/templates/calendar/agent-native.config.ts +5 -0
- package/corpus/templates/calendar/app/components/layout/AppLayout.tsx +4 -1
- package/corpus/templates/calendar/netlify.toml +3 -0
- package/corpus/templates/chat/agent-native.config.ts +5 -0
- package/corpus/templates/chat/netlify.toml +3 -0
- package/corpus/templates/clips/actions/lib/meeting-content.ts +28 -0
- package/corpus/templates/clips/actions/list-meetings.ts +33 -11
- package/corpus/templates/clips/app/i18n/en-US.ts +1 -0
- package/corpus/templates/clips/app/lib/meeting-history-query.ts +11 -0
- package/corpus/templates/clips/app/routes/_app.meetings._index.tsx +47 -21
- package/corpus/templates/clips/netlify.toml +4 -0
- package/corpus/templates/content/netlify.toml +3 -0
- package/corpus/templates/design/app/i18n-data.ts +2 -0
- package/corpus/templates/design/netlify.toml +3 -0
- package/corpus/templates/dispatch/netlify.toml +3 -0
- package/corpus/templates/factory/netlify.toml +3 -0
- package/corpus/templates/forms/netlify.toml +3 -0
- package/corpus/templates/macros/netlify.toml +3 -0
- package/corpus/templates/mail/agent-native.config.ts +5 -0
- package/corpus/templates/mail/netlify.toml +3 -0
- package/corpus/templates/plan/netlify.toml +3 -0
- package/corpus/templates/slides/netlify.toml +3 -0
- package/dist/agent/harness/acp-adapter.js +17 -2
- package/dist/agent/harness/ai-sdk-adapter.js +14 -3
- package/dist/agent/harness/background.js +10 -5
- package/dist/agent/harness/hosted.d.ts +20 -0
- package/dist/agent/harness/hosted.js +100 -0
- package/dist/agent/harness/runner.js +100 -77
- package/dist/agent/observational-memory/observer.js +12 -0
- package/dist/agent/production-agent.d.ts +3 -0
- package/dist/agent/production-agent.js +74 -4
- package/dist/agent/thread-data-builder.d.ts +12 -0
- package/dist/agent/thread-data-builder.js +23 -0
- package/dist/agent/types.d.ts +6 -0
- package/dist/client/AgentPanel.d.ts +5 -1
- package/dist/client/AgentPanel.js +113 -17
- package/dist/client/AgentTaskCard.d.ts +2 -2
- package/dist/client/AgentTaskCard.js +8 -22
- package/dist/client/AssistantChat.d.ts +8 -0
- package/dist/client/AssistantChat.js +106 -59
- package/dist/client/MultiTabAssistantChat.js +50 -6
- package/dist/client/NewWorkspaceAppFlow.js +7 -1
- package/dist/client/agent-chat-adapter.d.ts +6 -0
- package/dist/client/agent-chat-adapter.js +36 -8
- package/dist/client/app-chat-sidebar.d.ts +5 -0
- package/dist/client/app-chat-sidebar.js +53 -9
- package/dist/client/chat/composer-draft.d.ts +4 -0
- package/dist/client/chat/composer-draft.js +63 -0
- package/dist/client/chat-first/apps-rail.js +10 -1
- package/dist/client/chat-first/primary-nav.js +10 -5
- package/dist/client/frame-protocol.d.ts +1 -0
- package/dist/client/hooks/index.d.ts +1 -1
- package/dist/client/hooks/index.js +1 -1
- package/dist/client/i18n.js +5 -2
- package/dist/client/progress/RunsTray.js +129 -16
- package/dist/client/settings/SettingsRow.js +1 -1
- package/dist/client/use-chat-threads.js +11 -6
- package/dist/config.d.ts +11 -0
- package/dist/config.js +52 -0
- package/dist/extensions/actions.js +22 -1
- package/dist/hosted-harness/actions/get-hosted-harness-config.d.ts +2 -0
- package/dist/hosted-harness/actions/get-hosted-harness-config.js +13 -0
- package/dist/hosted-harness/actions/set-hosted-harness-enabled.d.ts +4 -0
- package/dist/hosted-harness/actions/set-hosted-harness-enabled.js +32 -0
- package/dist/localization/default-messages.d.ts +4 -1
- package/dist/localization/default-messages.js +5 -2
- package/dist/notifications/routes.d.ts +1 -1
- package/dist/provider-api/actions/custom-provider-registration.d.ts +6 -6
- package/dist/provider-api/actions/provider-api.d.ts +4 -4
- package/dist/server/action-discovery.js +12 -0
- package/dist/server/agent-chat-plugin.js +24 -4
- package/dist/server/agent-teams.d.ts +20 -12
- package/dist/server/agent-teams.js +69 -35
- package/dist/server/hosted-harness-policy.d.ts +17 -0
- package/dist/server/hosted-harness-policy.js +38 -0
- package/dist/server/poll.d.ts +4 -4
- package/dist/server/poll.js +45 -13
- package/dist/server/realtime-token.d.ts +1 -1
- package/dist/server/request-context.d.ts +4 -0
- package/dist/styles/agent-native.css +39 -0
- package/dist/templates/chat/agent-native.config.ts +5 -0
- package/dist/templates/chat/netlify.toml +3 -0
- package/dist/vite/action-types-plugin.js +8 -0
- package/package.json +5 -3
- package/src/templates/chat/agent-native.config.ts +5 -0
- package/src/templates/chat/netlify.toml +3 -0
|
@@ -25,6 +25,7 @@ import { Tooltip as DesignSystemTooltip } from "@agent-native/toolkit/design-sys
|
|
|
25
25
|
import { IconMessageCircle, IconMessageDots, IconTerminal2, IconSettings, IconLayoutSidebarRightCollapse, IconLayoutGrid, IconCheck, IconPlus, IconX, IconDotsVertical, IconHistory, IconArrowsHorizontal, IconArrowsMaximize, IconExternalLink, IconShare3, } from "@tabler/icons-react";
|
|
26
26
|
import React, { useState, useEffect, useRef, useCallback, useMemo, lazy, Suspense, startTransition, } from "react";
|
|
27
27
|
import { flushSync } from "react-dom";
|
|
28
|
+
import { hostedHarnessAgentOption, isHostedHarnessConfigured, isHostedHarnessRuntime, normalizeHostedHarnessRuntimes, } from "../agent/harness/hosted.js";
|
|
28
29
|
import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuTrigger, } from "./components/ui/dropdown-menu.js";
|
|
29
30
|
import { normalizeTooltipText } from "./components/ui/tooltip.js";
|
|
30
31
|
import { ErrorReportActions } from "./ErrorReportActions.js";
|
|
@@ -44,7 +45,8 @@ import { withBuilderUtmTrackingParams } from "../shared/builder-link-tracking.js
|
|
|
44
45
|
import { AGENT_SIDEBAR_MIN_WIDTH, consumeAgentSidebarUrlOpenOverride, clampAgentSidebarWidth, dispatchAgentSidebarStateChange, getAgentSidebarMaxWidth, getInitialAgentSidebarOpen, getAgentSidebarWideWidth, setAgentSidebarOpenPreference, subscribeAgentSidebarUrlChanges, SIDEBAR_STATE_CHANGE_EVENT, } from "./agent-sidebar-state.js";
|
|
45
46
|
import { trackEvent } from "./analytics.js";
|
|
46
47
|
import { agentNativePath, appPath, isWorkspaceAppPath } from "./api-path.js";
|
|
47
|
-
import { APP_CHAT_SIDEBAR_STATE_EVENT, APP_CHAT_SIDEBAR_STATE_REQUEST_MESSAGE, buildAppChatSidebarStateMessage, isPerAppChatStorageKey, } from "./app-chat-sidebar.js";
|
|
48
|
+
import { APP_CHAT_SIDEBAR_STATE_EVENT, APP_CHAT_SIDEBAR_STATE_REQUEST_MESSAGE, buildAppChatSidebarStateMessage, isPerAppChatStorageKey, requestPerAppChatCommand, usePerAppChatState, } from "./app-chat-sidebar.js";
|
|
49
|
+
import { injectedAgentNativeConfig } from "./app-config.js";
|
|
48
50
|
import { readClientAppState } from "./application-state.js";
|
|
49
51
|
import { assistantUiRecoverableRenderErrorKind } from "./assistant-ui-recovery.js";
|
|
50
52
|
import { shouldParentFrameOwnAgentPanel } from "./builder-frame.js";
|
|
@@ -58,6 +60,7 @@ import { useFirstRunOnboardingGateOwnsSurface } from "./onboarding/first-run-sta
|
|
|
58
60
|
import { useOnboardingPreviewMode } from "./onboarding/use-preview-mode.js";
|
|
59
61
|
import { recoverFromStaleChunkError } from "./route-chunk-recovery.js";
|
|
60
62
|
import { withBuilderConnectTrackingParams } from "./settings/useBuilderStatus.js";
|
|
63
|
+
import { useActionQuery } from "./use-action.js";
|
|
61
64
|
import { useScreenRefreshKey } from "./use-db-sync.js";
|
|
62
65
|
import { useDevMode } from "./use-dev-mode.js";
|
|
63
66
|
import { cn } from "./utils.js";
|
|
@@ -957,6 +960,7 @@ function AgentPanelInner({ defaultMode = "chat", className, style, apiUrl, empty
|
|
|
957
960
|
__html: "@media (hover:hover) and (pointer:fine){" +
|
|
958
961
|
".agent-sidebar-chat-header[data-agent-sidebar-chat-header]{opacity:0;pointer-events:none;transition:opacity 150ms ease-out;}" +
|
|
959
962
|
".agent-panel-root:hover .agent-sidebar-chat-header[data-agent-sidebar-chat-header],.agent-panel-root:focus-within .agent-sidebar-chat-header[data-agent-sidebar-chat-header],.agent-sidebar-chat-header[data-agent-sidebar-chat-header][data-agent-sidebar-chat-header-active]{opacity:1;pointer-events:auto;}" +
|
|
963
|
+
".agent-sidebar-panel[data-agent-sidebar-per-app-chat='true'] .agent-sidebar-chat-header[data-agent-sidebar-chat-header]{opacity:1;pointer-events:auto;transition:none;}" +
|
|
960
964
|
"}" +
|
|
961
965
|
".agent-tab-close{opacity:0}.agent-tab:hover .agent-tab-close{opacity:1}" +
|
|
962
966
|
".agent-tabs-scroll{scrollbar-width:none;-ms-overflow-style:none;}" +
|
|
@@ -1414,9 +1418,43 @@ export function AgentChatSurface({ mode = "panel", className, defaultMode = "cha
|
|
|
1414
1418
|
* Wraps app content with a toggleable agent sidebar.
|
|
1415
1419
|
* Use AgentToggleButton in your header to open/close it.
|
|
1416
1420
|
*/
|
|
1417
|
-
export function AgentSidebar({ children, emptyStateText = "How can I help you?", suggestions, dynamicSuggestions, composerToolbarSlot, composerSlot, onComposerTextChange, imageModelMenu, availableAgents, selectedAgent, onAgentChange, onConnectLocalRuntime, runtime, adapterReloadKey, threadFooterSlot, defaultSidebarWidth, sidebarWidth, position = "right", defaultOpen = false, animateMobile = true, animateDesktop = true, chatViewTransition = false, chatViewTransitionHandoff = false, storageKey, openStorageKey, apiUrl, agentChatSurface, showTabBar = true, suppressInlineOpenApp, composerPlaceholder, openOnChatRunning = false, onFullscreenRequest, scope, 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, runtime, adapterReloadKey, threadFooterSlot, defaultSidebarWidth, sidebarWidth, position = "right", defaultOpen = false, animateMobile = true, animateDesktop = true, chatViewTransition = false, chatViewTransitionHandoff = false, storageKey, openStorageKey, apiUrl, agentChatSurface, showTabBar = true, suppressInlineOpenApp, composerPlaceholder, openOnChatRunning = false, onFullscreenRequest, scope, showScopeBadge, browserTabId, threadUrlSync, agentPageHref, suppressFirstRunOnboarding = false, }) {
|
|
1422
|
+
const staticHostedHarnessEnabled = isHostedHarnessConfigured(injectedAgentNativeConfig().harness);
|
|
1423
|
+
const hostedHarnessQuery = useActionQuery("get-hosted-harness-config", undefined, { enabled: staticHostedHarnessEnabled });
|
|
1424
|
+
const hostedHarnessStatus = hostedHarnessQuery.data;
|
|
1425
|
+
const hostedHarnessEnabled = hostedHarnessStatus?.enabled === true;
|
|
1426
|
+
const hostedHarnessRuntimes = useMemo(() => hostedHarnessEnabled
|
|
1427
|
+
? normalizeHostedHarnessRuntimes(hostedHarnessStatus?.runtimes)
|
|
1428
|
+
: [], [hostedHarnessEnabled, hostedHarnessStatus?.runtimes]);
|
|
1429
|
+
const hostedHarnessUi = hostedHarnessEnabled;
|
|
1430
|
+
const hostedHarnessStorageKey = `agent-native-hosted-harness${storageKey ? `:${storageKey}` : ""}`;
|
|
1431
|
+
const [hostedHarnessRuntime, setHostedHarnessRuntime] = useState("claude-code");
|
|
1432
|
+
const hostedHarnessAgentOptions = useMemo(() => hostedHarnessRuntimes.map(hostedHarnessAgentOption), [hostedHarnessRuntimes]);
|
|
1433
|
+
const effectiveAvailableAgents = hostedHarnessEnabled
|
|
1434
|
+
? [
|
|
1435
|
+
...hostedHarnessAgentOptions,
|
|
1436
|
+
...(availableAgents ?? []).filter((agent) => !isHostedHarnessRuntime(agent.id)),
|
|
1437
|
+
]
|
|
1438
|
+
: availableAgents;
|
|
1439
|
+
const effectiveSelectedAgent = hostedHarnessEnabled
|
|
1440
|
+
? hostedHarnessRuntime
|
|
1441
|
+
: selectedAgent;
|
|
1442
|
+
const effectiveOnAgentChange = hostedHarnessEnabled
|
|
1443
|
+
? (agent) => {
|
|
1444
|
+
if (isHostedHarnessRuntime(agent)) {
|
|
1445
|
+
setHostedHarnessRuntime(agent);
|
|
1446
|
+
}
|
|
1447
|
+
onAgentChange?.(agent);
|
|
1448
|
+
}
|
|
1449
|
+
: onAgentChange;
|
|
1450
|
+
const effectivePosition = hostedHarnessUi ? "left" : position;
|
|
1451
|
+
const effectiveDefaultOpen = hostedHarnessUi || defaultOpen;
|
|
1452
|
+
const effectiveShowTabBar = hostedHarnessUi || showTabBar;
|
|
1453
|
+
const effectiveAnimateDesktop = hostedHarnessUi ? false : animateDesktop;
|
|
1418
1454
|
const sidebarOpenStorageKey = openStorageKey ?? storageKey;
|
|
1419
1455
|
const isPerAppChatSidebar = isPerAppChatStorageKey(sidebarOpenStorageKey);
|
|
1456
|
+
const perAppChatState = usePerAppChatState(!isPerAppChatSidebar);
|
|
1457
|
+
const isPerAppChatHosted = !isPerAppChatSidebar && perAppChatState.hosted === true;
|
|
1420
1458
|
const onboardingPreviewMode = useOnboardingPreviewMode();
|
|
1421
1459
|
const firstRunOnboardingGateOwnsSurface = useFirstRunOnboardingGateOwnsSurface();
|
|
1422
1460
|
const showFirstRunOnboarding = !firstRunOnboardingGateOwnsSurface &&
|
|
@@ -1424,7 +1462,7 @@ export function AgentSidebar({ children, emptyStateText = "How can I help you?",
|
|
|
1424
1462
|
(SHOW_FIRST_RUN_ONBOARDING || onboardingPreviewMode);
|
|
1425
1463
|
const initialWidth = defaultSidebarWidth ?? sidebarWidth ?? 380;
|
|
1426
1464
|
const [open, setOpen] = useState(() => openOnChatRunning ||
|
|
1427
|
-
getInitialAgentSidebarOpen(
|
|
1465
|
+
getInitialAgentSidebarOpen(effectiveDefaultOpen, sidebarOpenStorageKey));
|
|
1428
1466
|
const [presentationMode, setPresentationMode] = useState(false);
|
|
1429
1467
|
const [width, setWidth] = useState(initialWidth);
|
|
1430
1468
|
const [isWideDrawer, setIsWideDrawer] = useState(() => {
|
|
@@ -1485,6 +1523,45 @@ export function AgentSidebar({ children, emptyStateText = "How can I help you?",
|
|
|
1485
1523
|
return value;
|
|
1486
1524
|
});
|
|
1487
1525
|
}, [sidebarOpenStorageKey]);
|
|
1526
|
+
useEffect(() => {
|
|
1527
|
+
try {
|
|
1528
|
+
const saved = localStorage.getItem(hostedHarnessStorageKey);
|
|
1529
|
+
if (saved && isHostedHarnessRuntime(saved)) {
|
|
1530
|
+
setHostedHarnessRuntime(saved);
|
|
1531
|
+
}
|
|
1532
|
+
}
|
|
1533
|
+
catch {
|
|
1534
|
+
// coercion-ok: localStorage is optional persistence; memory state remains authoritative.
|
|
1535
|
+
// The picker falls back to Claude Code when storage is unavailable.
|
|
1536
|
+
}
|
|
1537
|
+
}, [hostedHarnessStorageKey]);
|
|
1538
|
+
useEffect(() => {
|
|
1539
|
+
if (!hostedHarnessEnabled || hostedHarnessRuntimes.length === 0)
|
|
1540
|
+
return;
|
|
1541
|
+
const next = hostedHarnessRuntimes.includes(hostedHarnessRuntime)
|
|
1542
|
+
? hostedHarnessRuntime
|
|
1543
|
+
: hostedHarnessRuntimes[0];
|
|
1544
|
+
if (!next)
|
|
1545
|
+
return;
|
|
1546
|
+
if (next !== hostedHarnessRuntime)
|
|
1547
|
+
setHostedHarnessRuntime(next);
|
|
1548
|
+
try {
|
|
1549
|
+
localStorage.setItem(hostedHarnessStorageKey, next);
|
|
1550
|
+
}
|
|
1551
|
+
catch {
|
|
1552
|
+
// coercion-ok: localStorage is optional persistence; memory state remains authoritative.
|
|
1553
|
+
// The selected runtime remains in memory for this tab.
|
|
1554
|
+
}
|
|
1555
|
+
}, [
|
|
1556
|
+
hostedHarnessEnabled,
|
|
1557
|
+
hostedHarnessRuntimes,
|
|
1558
|
+
hostedHarnessRuntime,
|
|
1559
|
+
hostedHarnessStorageKey,
|
|
1560
|
+
]);
|
|
1561
|
+
useEffect(() => {
|
|
1562
|
+
if (hostedHarnessUi)
|
|
1563
|
+
setOpenPersisted(true);
|
|
1564
|
+
}, [hostedHarnessUi, setOpenPersisted]);
|
|
1488
1565
|
const applyUrlOpenOverride = useCallback(() => {
|
|
1489
1566
|
const override = consumeAgentSidebarUrlOpenOverride(sidebarOpenStorageKey);
|
|
1490
1567
|
if (override !== null)
|
|
@@ -1495,9 +1572,9 @@ export function AgentSidebar({ children, emptyStateText = "How can I help you?",
|
|
|
1495
1572
|
return subscribeAgentSidebarUrlChanges(applyUrlOpenOverride);
|
|
1496
1573
|
}, [applyUrlOpenOverride]);
|
|
1497
1574
|
useEffect(() => {
|
|
1498
|
-
if (openOnChatRunning)
|
|
1575
|
+
if (openOnChatRunning && !isPerAppChatHosted)
|
|
1499
1576
|
setOpen(true);
|
|
1500
|
-
}, [openOnChatRunning]);
|
|
1577
|
+
}, [isPerAppChatHosted, openOnChatRunning]);
|
|
1501
1578
|
// Track whether the frame is controlling the sidebar (code mode = frame active).
|
|
1502
1579
|
// Default to true when inside an iframe — assume the frame sidebar is active
|
|
1503
1580
|
// until told otherwise. This prevents both sidebars flashing after hot reloads.
|
|
@@ -1519,7 +1596,8 @@ export function AgentSidebar({ children, emptyStateText = "How can I help you?",
|
|
|
1519
1596
|
const [hasFrameSidebarState, setHasFrameSidebarState] = useState(false);
|
|
1520
1597
|
const [backgroundPanelActive, setBackgroundPanelActive] = useState(false);
|
|
1521
1598
|
const [runningTabIds, setRunningTabIds] = useState(() => new Set());
|
|
1522
|
-
const shouldMountPanel = !
|
|
1599
|
+
const shouldMountPanel = !isPerAppChatHosted &&
|
|
1600
|
+
!presentationMode &&
|
|
1523
1601
|
(!frameCodeMode || !shouldParentFrameOwnAgentPanel()) &&
|
|
1524
1602
|
(open || backgroundPanelActive || runningTabIds.size > 0);
|
|
1525
1603
|
const shouldMountPanelRef = useRef(shouldMountPanel);
|
|
@@ -1531,10 +1609,12 @@ export function AgentSidebar({ children, emptyStateText = "How can I help you?",
|
|
|
1531
1609
|
// Skip the initial emit in frame-owned mode — wait until the frame has
|
|
1532
1610
|
// sent us its real sidebar state. Once we know, this effect re-runs and
|
|
1533
1611
|
// dispatches the correct value.
|
|
1534
|
-
if (frameOwned && !hasFrameSidebarState)
|
|
1612
|
+
if (frameOwned && !hasFrameSidebarState && !isPerAppChatHosted)
|
|
1535
1613
|
return;
|
|
1536
1614
|
dispatchAgentSidebarStateChange({
|
|
1537
|
-
open:
|
|
1615
|
+
open: isPerAppChatHosted
|
|
1616
|
+
? perAppChatState.open
|
|
1617
|
+
: !presentationMode && (frameOwned ? frameSidebarOpen : open),
|
|
1538
1618
|
source: frameOwned ? "frame" : "app",
|
|
1539
1619
|
mode: frameOwned ? "code" : "app",
|
|
1540
1620
|
});
|
|
@@ -1544,6 +1624,8 @@ export function AgentSidebar({ children, emptyStateText = "How can I help you?",
|
|
|
1544
1624
|
open,
|
|
1545
1625
|
presentationMode,
|
|
1546
1626
|
hasFrameSidebarState,
|
|
1627
|
+
isPerAppChatHosted,
|
|
1628
|
+
perAppChatState.open,
|
|
1547
1629
|
]);
|
|
1548
1630
|
useEffect(() => {
|
|
1549
1631
|
if (!isPerAppChatSidebar)
|
|
@@ -1583,7 +1665,7 @@ export function AgentSidebar({ children, emptyStateText = "How can I help you?",
|
|
|
1583
1665
|
? detail.tabId
|
|
1584
1666
|
: "__default__";
|
|
1585
1667
|
if (detail?.isRunning === true) {
|
|
1586
|
-
if (openOnChatRunning)
|
|
1668
|
+
if (openOnChatRunning && !isPerAppChatHosted)
|
|
1587
1669
|
setOpen(true);
|
|
1588
1670
|
setRunningTabIds((prev) => {
|
|
1589
1671
|
const next = new Set(prev);
|
|
@@ -1609,7 +1691,7 @@ export function AgentSidebar({ children, emptyStateText = "How can I help you?",
|
|
|
1609
1691
|
window.removeEventListener(AGENT_PANEL_PREPARE_EVENT, preparePanel);
|
|
1610
1692
|
window.removeEventListener(AGENT_CHAT_RUNNING_EVENT, handleChatRunning);
|
|
1611
1693
|
};
|
|
1612
|
-
}, [openOnChatRunning, setOpenPersisted]);
|
|
1694
|
+
}, [isPerAppChatHosted, openOnChatRunning, setOpenPersisted]);
|
|
1613
1695
|
useEffect(() => {
|
|
1614
1696
|
const replayAfterMount = (type, event) => {
|
|
1615
1697
|
if (shouldMountPanelRef.current)
|
|
@@ -1639,6 +1721,10 @@ export function AgentSidebar({ children, emptyStateText = "How can I help you?",
|
|
|
1639
1721
|
}, [setOpenPersisted]);
|
|
1640
1722
|
useEffect(() => {
|
|
1641
1723
|
const toggleHandler = () => {
|
|
1724
|
+
if (isPerAppChatHosted) {
|
|
1725
|
+
requestPerAppChatCommand("toggle");
|
|
1726
|
+
return;
|
|
1727
|
+
}
|
|
1642
1728
|
if (frameCodeMode && shouldParentFrameOwnAgentPanel()) {
|
|
1643
1729
|
// Forward toggle to frame parent — the frame sidebar handles it
|
|
1644
1730
|
window.parent.postMessage({ type: "agentNative.toggleSidebar" }, parentFrameTargetOrigin());
|
|
@@ -1648,6 +1734,10 @@ export function AgentSidebar({ children, emptyStateText = "How can I help you?",
|
|
|
1648
1734
|
}
|
|
1649
1735
|
};
|
|
1650
1736
|
const openHandler = () => {
|
|
1737
|
+
if (isPerAppChatHosted) {
|
|
1738
|
+
requestPerAppChatCommand("open");
|
|
1739
|
+
return;
|
|
1740
|
+
}
|
|
1651
1741
|
if (frameCodeMode && shouldParentFrameOwnAgentPanel()) {
|
|
1652
1742
|
window.parent.postMessage({ type: "agentNative.toggleSidebar", data: { open: true } }, parentFrameTargetOrigin());
|
|
1653
1743
|
}
|
|
@@ -1656,6 +1746,10 @@ export function AgentSidebar({ children, emptyStateText = "How can I help you?",
|
|
|
1656
1746
|
}
|
|
1657
1747
|
};
|
|
1658
1748
|
const closeHandler = () => {
|
|
1749
|
+
if (isPerAppChatHosted) {
|
|
1750
|
+
requestPerAppChatCommand("close");
|
|
1751
|
+
return;
|
|
1752
|
+
}
|
|
1659
1753
|
if (frameCodeMode && shouldParentFrameOwnAgentPanel()) {
|
|
1660
1754
|
window.parent.postMessage({ type: "agentNative.toggleSidebar", data: { open: false } }, parentFrameTargetOrigin());
|
|
1661
1755
|
}
|
|
@@ -1671,7 +1765,7 @@ export function AgentSidebar({ children, emptyStateText = "How can I help you?",
|
|
|
1671
1765
|
window.removeEventListener("agent-panel:open", openHandler);
|
|
1672
1766
|
window.removeEventListener("agent-panel:close", closeHandler);
|
|
1673
1767
|
};
|
|
1674
|
-
}, [setOpenPersisted, frameCodeMode]);
|
|
1768
|
+
}, [setOpenPersisted, frameCodeMode, isPerAppChatHosted]);
|
|
1675
1769
|
// Listen for sidebar mode commands from the frame parent.
|
|
1676
1770
|
// When frame is in "code" mode, hide the app sidebar.
|
|
1677
1771
|
// When frame is in "app" mode, show the app sidebar, sync width and panel mode.
|
|
@@ -1848,10 +1942,10 @@ export function AgentSidebar({ children, emptyStateText = "How can I help you?",
|
|
|
1848
1942
|
}, [runDrawerMorph, drawerPlaceholderWidth, isWideDrawer]);
|
|
1849
1943
|
const handleResizeStart = useCallback(() => setIsResizing(true), []);
|
|
1850
1944
|
const handleResizeEnd = useCallback(() => setIsResizing(false), []);
|
|
1851
|
-
const isLeft =
|
|
1945
|
+
const isLeft = effectivePosition === "left";
|
|
1852
1946
|
const wideDrawerEnabled = isWideDrawer && !isMobile;
|
|
1853
1947
|
const mobileAnimationEnabled = !presentationMode && isMobile && animateMobile;
|
|
1854
|
-
const desktopAnimationEnabled = !presentationMode && !isMobile &&
|
|
1948
|
+
const desktopAnimationEnabled = !presentationMode && !isMobile && effectiveAnimateDesktop;
|
|
1855
1949
|
const sidebarAnimationEnabled = mobileAnimationEnabled || desktopAnimationEnabled;
|
|
1856
1950
|
const [renderAnimatedPanel, setRenderAnimatedPanel] = useState(shouldMountPanel);
|
|
1857
1951
|
useEffect(() => {
|
|
@@ -1940,6 +2034,7 @@ export function AgentSidebar({ children, emptyStateText = "How can I help you?",
|
|
|
1940
2034
|
background: "var(--agent-sidebar-background)",
|
|
1941
2035
|
width: desktopAnimationEnabled ? undefined : width,
|
|
1942
2036
|
maxHeight: "var(--agent-native-viewport-height, 100vh)",
|
|
2037
|
+
zIndex: hostedHarnessUi ? SIDEBAR_OVERLAY_Z_INDEX : undefined,
|
|
1943
2038
|
borderLeft: !panelOpen || isLeft || showResizeHandle
|
|
1944
2039
|
? "none"
|
|
1945
2040
|
: "1px solid hsl(var(--border))",
|
|
@@ -1956,17 +2051,18 @@ export function AgentSidebar({ children, emptyStateText = "How can I help you?",
|
|
|
1956
2051
|
}
|
|
1957
2052
|
// Mount the live chat surface only while visible or actively needed. Keeping
|
|
1958
2053
|
// it mounted while closed starts app-state polling on every public page view.
|
|
1959
|
-
const sidebar = shouldRenderPanel ? (_jsxs(_Fragment, { children: [showResizeHandle && !isLeft && (_jsx(ResizeHandle, { position:
|
|
2054
|
+
const sidebar = shouldRenderPanel ? (_jsxs(_Fragment, { children: [showResizeHandle && !isLeft && (_jsx(ResizeHandle, { position: effectivePosition, onDrag: handleDrag, onResizeStart: handleResizeStart, onResizeEnd: handleResizeEnd })), _jsx("div", { className: cn("agent-sidebar-panel flex shrink-0 flex-col overflow-hidden text-[13px] leading-[1.2] antialiased", chatViewTransition && AGENT_CHAT_VIEW_TRANSITION_CLASS), "data-agent-sidebar-animation": wideDrawerEnabled
|
|
1960
2055
|
? "drawer"
|
|
1961
2056
|
: mobileAnimationEnabled
|
|
1962
2057
|
? "mobile"
|
|
1963
2058
|
: desktopAnimationEnabled
|
|
1964
2059
|
? "desktop"
|
|
1965
|
-
: undefined, "data-agent-sidebar-layout": panelLayout, "data-agent-sidebar-position":
|
|
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
|
|
1966
2061
|
? getAgentChatViewTransitionStyle(panelStyle)
|
|
1967
|
-
: 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:
|
|
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, 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, 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;
|
|
1968
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;
|
|
1969
|
-
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":
|
|
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
|
+
!isPerAppChatHosted &&
|
|
1970
2066
|
!presentationMode &&
|
|
1971
2067
|
(mobileAnimationEnabled ? shouldRenderPanel : open) && (_jsx("div", { className: cn("agent-sidebar-backdrop fixed inset-0 bg-foreground/40", mobileAnimationEnabled && !panelOpen && "pointer-events-none"), "data-agent-sidebar-animation": mobileAnimationEnabled ? "mobile" : undefined, "data-agent-sidebar-state": panelOpen ? "open" : "closed", style: { zIndex: SIDEBAR_OVERLAY_Z_INDEX - 1 }, onClick: () => setOpenPersisted(false) })), shouldMountPanel ? _jsx(URLSync, { browserTabId: browserTabId }) : null, isResizing ? (_jsx("div", { "aria-hidden": "true", className: "agent-sidebar-resize-overlay" })) : null, isLeft && !presentationMode ? sidebar : null, isLeft && !presentationMode ? drawerPlaceholder : null, _jsx("div", { className: "agent-sidebar-main-surface flex flex-1 flex-col overflow-auto min-w-0", "data-agent-sidebar-main-position": position, "data-agent-sidebar-main-state": !isMobile && !presentationMode && panelOpen ? "open" : "closed", "data-agent-sidebar-resizing": isResizing ? "true" : undefined, children: _jsx(ScreenRefreshBoundary, { children: children }) }), !isLeft && !presentationMode ? drawerPlaceholder : null, !isLeft && !presentationMode ? sidebar : null] })] }) }));
|
|
1972
2068
|
}
|
|
@@ -6,7 +6,7 @@ export interface AgentTaskCardProps {
|
|
|
6
6
|
onOpen?: (threadId: string) => void;
|
|
7
7
|
}
|
|
8
8
|
/**
|
|
9
|
-
*
|
|
10
|
-
* CustomEvents to update its
|
|
9
|
+
* Inline tool-call presentation for a spawned sub-agent. Listens for
|
|
10
|
+
* agent-task-event CustomEvents to update its streamed output in real-time.
|
|
11
11
|
*/
|
|
12
12
|
export declare function AgentTaskCard({ taskId, threadId, description, onOpen, }: AgentTaskCardProps): React.JSX.Element;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { IconLoader2,
|
|
1
|
+
import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { IconLoader2, IconChevronRight, IconExternalLink, IconAlertCircle, IconPlayerStop, IconSubtask, } from "@tabler/icons-react";
|
|
3
3
|
import { useState, useEffect, useRef, useCallback } from "react";
|
|
4
4
|
import ReactMarkdown from "react-markdown";
|
|
5
5
|
import remarkGfm from "remark-gfm";
|
|
@@ -7,8 +7,8 @@ import { agentNativePath } from "./api-path.js";
|
|
|
7
7
|
import { useT } from "./i18n.js";
|
|
8
8
|
import { cn } from "./utils.js";
|
|
9
9
|
/**
|
|
10
|
-
*
|
|
11
|
-
* CustomEvents to update its
|
|
10
|
+
* Inline tool-call presentation for a spawned sub-agent. Listens for
|
|
11
|
+
* agent-task-event CustomEvents to update its streamed output in real-time.
|
|
12
12
|
*/
|
|
13
13
|
export function AgentTaskCard({ taskId, threadId, description, onOpen, }) {
|
|
14
14
|
const t = useT();
|
|
@@ -127,24 +127,10 @@ export function AgentTaskCard({ taskId, threadId, description, onOpen, }) {
|
|
|
127
127
|
const isError = status === "errored";
|
|
128
128
|
const taskTitle = description.trim() || "Task";
|
|
129
129
|
const currentStepText = currentStep.trim();
|
|
130
|
-
const statusLabel = isRunning ? "Running" : isError ? "Error" : "Done";
|
|
131
|
-
const statusClassName = cn("inline-flex h-5 shrink-0 items-center gap-1 rounded-md px-1.5 text-[10px] font-medium", isError
|
|
132
|
-
? "bg-destructive/10 text-destructive"
|
|
133
|
-
: isComplete
|
|
134
|
-
? "bg-emerald-500/10 text-emerald-600 dark:text-emerald-400"
|
|
135
|
-
: "bg-muted text-muted-foreground");
|
|
136
130
|
const displayText = isComplete && summary ? summary : preview;
|
|
137
131
|
const hasContent = displayText.length > 0;
|
|
138
|
-
const
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
: "No summary available";
|
|
143
|
-
return (_jsxs("div", { className: cn("my-2 overflow-hidden rounded-lg border bg-background/50 transition-colors", isError
|
|
144
|
-
? "border-destructive/30"
|
|
145
|
-
: isComplete
|
|
146
|
-
? "border-emerald-500/20"
|
|
147
|
-
: "border-border"), children: [_jsxs("button", { type: "button", "aria-expanded": expanded, className: "flex w-full items-center gap-2 px-3 py-2 text-start transition-colors hover:bg-muted/45", onClick: () => setExpanded(!expanded), children: [_jsxs("span", { className: "inline-flex h-5 shrink-0 items-center gap-1 rounded-md border border-border/60 bg-background/70 px-1.5 text-[10px] font-medium text-muted-foreground", children: [_jsx(IconSubtask, { className: "h-3 w-3" }), t("agentTask.backgroundTask")] }), _jsx("span", { className: "min-w-0 flex-1 truncate text-xs font-medium text-foreground", children: taskTitle }), _jsxs("span", { className: statusClassName, children: [isRunning ? (_jsx(IconLoader2, { className: "h-3 w-3 animate-spin" })) : isError ? (_jsx(IconAlertCircle, { className: "h-3 w-3" })) : (_jsx(IconCheck, { className: "h-3 w-3" })), statusLabel] }), _jsx(IconChevronRight, { className: cn("h-3 w-3 shrink-0 text-muted-foreground/40 transition-transform duration-150", expanded && "rotate-90", "rtl:-scale-x-100") })] }), expanded && isRunning && currentStepText && (_jsxs("div", { className: "flex gap-1.5 border-t border-border/60 px-3 py-1.5 text-[11px] text-muted-foreground", children: [_jsx("span", { className: "shrink-0 font-medium text-foreground/70", children: "Now:" }), _jsx("span", { className: "min-w-0 break-words", children: currentStepText })] })), expanded && hasContent && (_jsx("div", { className: "px-3 pb-2 pt-1", children: _jsx("div", { ref: previewRef, className: "agent-markdown prose prose-sm prose-invert max-h-48 max-w-none overflow-y-auto break-words rounded-md border border-border/50 bg-muted/25 px-3 py-2 text-xs text-muted-foreground", children: _jsx(ReactMarkdown, { remarkPlugins: [remarkGfm], children: displayText.length > 800
|
|
148
|
-
? "..." + displayText.slice(-800)
|
|
149
|
-
: displayText }) }) })), expanded && (_jsxs("div", { className: "flex items-center justify-between gap-2 px-3 pb-2", children: [_jsx("span", { className: "min-w-0 flex-1 truncate text-[10px] text-muted-foreground/60", children: !hasContent ? emptyMessage : "" }), _jsxs("div", { className: "flex shrink-0 items-center gap-1", children: [isRunning && (_jsxs("button", { onClick: handleStop, className: "inline-flex cursor-pointer items-center gap-1 rounded-md px-2 py-1 text-[11px] font-medium text-muted-foreground hover:bg-muted hover:text-destructive", "aria-label": t("agentTask.stop"), children: [_jsx(IconPlayerStop, { className: "h-3 w-3" }), "Stop"] })), _jsxs("button", { onClick: handleOpen, className: "inline-flex cursor-pointer items-center gap-1 rounded-md px-2 py-1 text-[11px] font-medium text-muted-foreground hover:bg-muted hover:text-foreground", children: [t("agentTask.openThread"), _jsx(IconExternalLink, { className: "h-3 w-3" })] })] })] }))] }));
|
|
132
|
+
const statusLabel = isRunning ? "Running" : isError ? "Error" : "Done";
|
|
133
|
+
return (_jsxs("div", { className: "group/agent my-0.5 w-full", children: [_jsxs("button", { type: "button", "aria-expanded": expanded, className: "flex w-full items-center gap-1.5 rounded-md py-0.5 text-left text-[13px] text-muted-foreground transition-colors hover:text-foreground", onClick: () => setExpanded(!expanded), children: [_jsx("span", { className: "relative flex size-4 shrink-0 items-center justify-center", children: isRunning ? (_jsx(IconLoader2, { className: "size-3.5 animate-spin" })) : isError ? (_jsx(IconAlertCircle, { className: "size-3.5 text-destructive" })) : (_jsxs(_Fragment, { children: [_jsx(IconSubtask, { className: cn("size-3.5 transition-opacity", "group-hover/agent:opacity-0") }), _jsx(IconChevronRight, { className: cn("absolute size-3.5 opacity-0 transition-[opacity,transform] group-hover/agent:opacity-100", expanded && "rotate-90") })] })) }), _jsxs("span", { className: cn("min-w-0 truncate font-normal", isRunning && "agent-running-shimmer"), children: [t("agentTask.spawnedAgent"), ": ", taskTitle] }), _jsx("span", { className: "sr-only", children: statusLabel })] }), expanded && (_jsxs("div", { className: "ms-1 border-s border-border/50 ps-2 pt-1", children: [isRunning && currentStepText && (_jsx("p", { className: "ps-5 pb-1 text-xs text-muted-foreground", "aria-live": "polite", children: currentStepText })), hasContent && (_jsx("div", { className: "ps-5 pb-1", children: _jsx("div", { ref: previewRef, "aria-live": isRunning ? "polite" : undefined, "data-streaming": isRunning ? "true" : undefined, className: "agent-markdown prose prose-sm prose-invert max-h-48 max-w-none overflow-y-auto break-words text-xs text-muted-foreground", children: _jsx(ReactMarkdown, { remarkPlugins: [remarkGfm], children: displayText.length > 800
|
|
134
|
+
? "..." + displayText.slice(-800)
|
|
135
|
+
: displayText }) }) })), _jsxs("div", { className: "flex items-center gap-1 ps-5 pb-1", children: [isRunning && (_jsxs("button", { onClick: handleStop, className: "inline-flex cursor-pointer items-center gap-1 rounded-md px-1.5 py-0.5 text-xs text-muted-foreground transition-colors hover:bg-muted hover:text-destructive", "aria-label": t("agentTask.stop"), children: [_jsx(IconPlayerStop, { className: "size-3" }), "Stop"] })), _jsxs("button", { onClick: handleOpen, className: "inline-flex cursor-pointer items-center gap-1 rounded-md px-1.5 py-0.5 text-xs text-muted-foreground transition-colors hover:bg-muted hover:text-foreground", children: [t("agentTask.openThread"), _jsx(IconExternalLink, { className: "size-3" })] })] })] }))] }));
|
|
150
136
|
}
|
|
@@ -242,6 +242,12 @@ export interface AssistantChatAdapterContext {
|
|
|
242
242
|
effortRef: {
|
|
243
243
|
current: ReasoningEffort | undefined;
|
|
244
244
|
};
|
|
245
|
+
harnessRef?: {
|
|
246
|
+
current: string | undefined;
|
|
247
|
+
};
|
|
248
|
+
hostedHarnessRef?: {
|
|
249
|
+
current: boolean;
|
|
250
|
+
};
|
|
245
251
|
execModeRef: {
|
|
246
252
|
current: "build" | "plan" | undefined;
|
|
247
253
|
};
|
|
@@ -369,6 +375,8 @@ export interface AssistantChatProps {
|
|
|
369
375
|
availableAgents?: ComposerAgentOption[];
|
|
370
376
|
/** Selected agent runtime identifier. */
|
|
371
377
|
selectedAgent?: string;
|
|
378
|
+
/** Mark the selected runtime as the hosted tools-only harness mode. */
|
|
379
|
+
hostedHarness?: boolean;
|
|
372
380
|
/** Callback when the user picks an agent runtime. */
|
|
373
381
|
onAgentChange?: (agent: string) => void;
|
|
374
382
|
/**
|