@agent-native/core 0.157.9 → 0.157.10
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/templates/analytics/scripts/first-party-analytics-postgres-retention-dry-run.sql +5 -2
- package/corpus/templates/analytics/server/lib/first-party-analytics-backend.ts +3 -1
- package/corpus/templates/analytics/server/lib/first-party-analytics-purge.ts +18 -6
- package/corpus/templates/analytics/server/plugins/db.ts +139 -0
- package/corpus/templates/slides/AGENTS.md +14 -10
- package/corpus/templates/slides/actions/export-pptx.ts +1094 -94
- package/corpus/templates/slides/actions/import-file.ts +16 -1
- package/corpus/templates/slides/actions/import-pptx.ts +61 -43
- package/corpus/templates/slides/app/components/deck/SlideRenderer.tsx +222 -29
- package/corpus/templates/slides/app/components/editor/ExportMenu.tsx +71 -0
- package/corpus/templates/slides/app/global.css +19 -1
- package/corpus/templates/slides/app/lib/export-google-slides-client.ts +44 -5
- package/corpus/templates/slides/app/lib/export-pdf-client.ts +13 -6
- package/corpus/templates/slides/app/lib/export-pptx-client.ts +556 -25
- package/corpus/templates/slides/app/pages/DeckEditor.tsx +18 -1
- package/corpus/templates/slides/server/handlers/import/html-converter.ts +1176 -26
- package/corpus/templates/slides/server/handlers/import/pdf-fidelity-parser.ts +13 -0
- package/corpus/templates/slides/server/handlers/import/pptx-assets.ts +24 -0
- package/corpus/templates/slides/shared/aspect-ratios.ts +13 -1
- package/dist/agent/harness/migrations.js +24 -3
- package/dist/agent/production-agent.js +11 -0
- package/dist/agent/run-loop-with-resume.js +21 -4
- package/dist/automations/service.d.ts +6 -0
- package/dist/automations/service.js +35 -0
- package/dist/cli/code-agent-connector.d.ts +4 -1
- package/dist/cli/code-agent-connector.js +154 -23
- package/dist/cli/code-agent-executor.js +255 -13
- package/dist/cli/code-agent-runs.d.ts +1 -0
- package/dist/cli/code-agent-runs.js +2 -1
- package/dist/cli/portal-workspace.d.ts +49 -0
- package/dist/cli/portal-workspace.js +320 -0
- package/dist/client/AssistantChat.d.ts +1 -1
- package/dist/client/AssistantChat.js +39 -61
- package/dist/client/ConnectBuilderCard.js +33 -5
- package/dist/client/agent-chat-adapter.js +4 -0
- package/dist/client/analytics-platform.d.ts +2 -0
- package/dist/client/analytics-platform.js +12 -0
- package/dist/client/analytics.d.ts +3 -0
- package/dist/client/analytics.js +10 -1
- package/dist/client/chat/index.d.ts +1 -0
- package/dist/client/chat/index.js +1 -0
- package/dist/client/chat/run-recovery.d.ts +2 -1
- package/dist/client/chat/run-recovery.js +2 -2
- package/dist/client/chat-first/apps-rail.d.ts +1 -1
- package/dist/client/chat-first/apps-rail.js +11 -11
- package/dist/client/chat-first/surface-tabs.d.ts +1 -1
- package/dist/client/chat-first/surface-tabs.js +38 -36
- package/dist/client/chat-first/types.d.ts +5 -0
- package/dist/client/chat-first.d.ts +1 -1
- package/dist/client/chat-first.js +4 -4
- package/dist/client/desktop-local-code-change.d.ts +10 -0
- package/dist/client/desktop-local-code-change.js +16 -0
- package/dist/client/index.d.ts +1 -0
- package/dist/client/index.js +1 -0
- package/dist/client/observability/ThumbsFeedback.js +21 -7
- package/dist/client/terminal/AgentTerminal.d.ts +9 -1
- package/dist/client/terminal/AgentTerminal.js +38 -3
- package/dist/client/terminal/index.d.ts +1 -1
- package/dist/client/terminal/index.js +1 -1
- package/dist/client/track.js +9 -1
- package/dist/client/use-action.js +3 -0
- package/dist/collab/struct-routes.d.ts +1 -1
- package/dist/deploy/build.js +1 -1
- package/dist/ingestion/pptx.d.ts +78 -0
- package/dist/ingestion/pptx.js +991 -107
- package/dist/integrations/index.d.ts +3 -3
- package/dist/integrations/index.js +2 -2
- package/dist/integrations/plugin.js +95 -6
- package/dist/integrations/remote-commands-store.d.ts +5 -0
- package/dist/integrations/remote-commands-store.js +63 -22
- package/dist/integrations/remote-devices-store.d.ts +2 -1
- package/dist/integrations/remote-devices-store.js +46 -0
- package/dist/integrations/remote-types.d.ts +20 -0
- package/dist/jobs/actions/list-recurring-jobs.d.ts +3 -0
- package/dist/jobs/actions/list-recurring-jobs.js +5 -1
- package/dist/jobs/frontmatter.d.ts +16 -0
- package/dist/jobs/frontmatter.js +53 -0
- package/dist/jobs/remote-execution.d.ts +42 -0
- package/dist/jobs/remote-execution.js +287 -0
- package/dist/jobs/scheduler.js +102 -3
- package/dist/jobs/tools.js +50 -3
- package/dist/notifications/routes.d.ts +4 -4
- package/dist/provider-api/actions/custom-provider-registration.d.ts +9 -9
- package/dist/provider-api/actions/provider-api.d.ts +14 -14
- package/dist/provider-api/corpus-jobs.d.ts +2 -2
- package/dist/resources/handlers.d.ts +1 -1
- package/dist/server/action-routes.js +4 -2
- package/dist/server/agent-chat-plugin.js +6 -0
- package/dist/server/agent-run-context.d.ts +1 -0
- package/dist/server/agent-run-context.js +9 -0
- package/dist/server/core-routes-plugin.js +8 -1
- package/dist/server/request-context.d.ts +2 -0
- package/dist/shared/analytics-platform.d.ts +6 -0
- package/dist/shared/analytics-platform.js +14 -0
- package/dist/shared/mcp-embed-headers.d.ts +1 -1
- package/dist/shared/mcp-embed-headers.js +1 -1
- package/dist/styles/agent-native.css +83 -103
- package/dist/terminal/cli-registry.js +5 -0
- package/dist/tracking/registry.js +9 -1
- package/dist/triggers/actions/list-automations.d.ts +3 -0
- package/dist/triggers/actions/list-automations.js +3 -0
- package/dist/triggers/actions/manage-automation.d.ts +9 -0
- package/dist/triggers/actions/manage-automation.js +14 -2
- package/dist/triggers/actions.js +82 -7
- package/docs/content/template-content-developers.mdx +48 -0
- package/docs/content/toolkit-ui.mdx +57 -0
- package/package.json +2 -2
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import { unwrapAttachmentEnvelope } from "@agent-native/toolkit/composer/pasted-text";
|
|
2
2
|
import { actionPreparationContinuationNote } from "../agent/action-continuation-guidance.js";
|
|
3
3
|
import { LLM_MISSING_CREDENTIALS_ERROR_CODE, LLM_MISSING_CREDENTIALS_MESSAGE, } from "../agent/engine/credential-errors.js";
|
|
4
|
+
import { ANALYTICS_CLIENT_PLATFORM_HEADER } from "../shared/analytics-platform.js";
|
|
4
5
|
import { clearPendingTurnIfMatches, getActiveRun, setActiveRun, updateActiveRunSeq, clearActiveRun, clearActiveRunIfMatches, setPendingTurn, } from "./active-run-state.js";
|
|
6
|
+
import { getAnalyticsClientPlatform } from "./analytics-platform.js";
|
|
5
7
|
import { getOrCreateAnalyticsSessionId } from "./analytics-session.js";
|
|
6
8
|
import { captureError } from "./analytics.js";
|
|
7
9
|
import { agentNativePath } from "./api-path.js";
|
|
@@ -2000,6 +2002,8 @@ export function createAgentChatAdapter(options) {
|
|
|
2000
2002
|
catch {
|
|
2001
2003
|
// Analytics session unavailable — traces just lose replay linkage.
|
|
2002
2004
|
}
|
|
2005
|
+
headers[ANALYTICS_CLIENT_PLATFORM_HEADER] =
|
|
2006
|
+
getAnalyticsClientPlatform();
|
|
2003
2007
|
// Surface hint — the server uses this to keep code-editing dev tools
|
|
2004
2008
|
// out of the app-rendered sidebar. The outer dev frame passes
|
|
2005
2009
|
// "dev-frame" explicitly; the reusable in-product chat defaults to
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { normalizeAnalyticsClientPlatform, } from "../shared/analytics-platform.js";
|
|
2
|
+
export function getAnalyticsClientPlatform(configured) {
|
|
3
|
+
if (configured)
|
|
4
|
+
return configured;
|
|
5
|
+
if (typeof window === "undefined")
|
|
6
|
+
return "web";
|
|
7
|
+
const platformWindow = window;
|
|
8
|
+
return (normalizeAnalyticsClientPlatform(platformWindow.agentNativeDesktop?.analytics?.clientPlatform) ??
|
|
9
|
+
normalizeAnalyticsClientPlatform(platformWindow.__AGENT_NATIVE_HOST_PLATFORM__) ??
|
|
10
|
+
normalizeAnalyticsClientPlatform(platformWindow.__AGENT_NATIVE_CONFIG__?.clientPlatform) ??
|
|
11
|
+
"web");
|
|
12
|
+
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { type AnalyticsClientPlatform } from "../shared/analytics-platform.js";
|
|
1
2
|
export { clearAnalyticsSessionId, setAnalyticsSessionId, } from "./analytics-session.js";
|
|
2
3
|
import type { SessionReplayOptions, SessionReplayStartResult } from "./session-replay.js";
|
|
3
4
|
export { scrubUrl } from "./url-scrub.js";
|
|
@@ -51,6 +52,8 @@ export type ErrorCaptureConfigOptions = {
|
|
|
51
52
|
maxBreadcrumbs?: number;
|
|
52
53
|
};
|
|
53
54
|
export type ConfigureTrackingOptions = {
|
|
55
|
+
/** Platform attribution attached to every event emitted by this client. */
|
|
56
|
+
clientPlatform?: AnalyticsClientPlatform;
|
|
54
57
|
/**
|
|
55
58
|
* Agent Native first-party analytics public key. This mirrors hosted
|
|
56
59
|
* analytics SDKs where consumers pass the key at setup time instead of
|
package/dist/client/analytics.js
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
|
+
import { ANALYTICS_CLIENT_PLATFORM_PROPERTY, } from "../shared/analytics-platform.js";
|
|
1
2
|
import { llmConnectionTrackingProperties, } from "../shared/llm-connection.js";
|
|
2
3
|
import { toPostHogExceptionProperties } from "../tracking/posthog-exception.js";
|
|
4
|
+
import { getAnalyticsClientPlatform } from "./analytics-platform.js";
|
|
3
5
|
import { getOrCreateAnalyticsAnonymousId, getOrCreateAnalyticsSessionId, } from "./analytics-session.js";
|
|
4
6
|
export { clearAnalyticsSessionId, setAnalyticsSessionId, } from "./analytics-session.js";
|
|
5
7
|
import { fetchAgentEngineStatus, fetchAuthSessionStatus, } from "./client-status-requests.js";
|
|
@@ -10,6 +12,7 @@ export { scrubUrl } from "./url-scrub.js";
|
|
|
10
12
|
export { addErrorBreadcrumb, captureException, captureMessage, isErrorCaptureInstalled, } from "./error-capture.js";
|
|
11
13
|
export { getSessionReplayContext, getSessionReplayUrl, } from "./session-replay.js";
|
|
12
14
|
let _getDefaultProps = null;
|
|
15
|
+
let _configuredAnalyticsClientPlatform = null;
|
|
13
16
|
let _agentNativeAnalyticsPublicKey = null;
|
|
14
17
|
let _agentNativeAnalyticsEndpoint = null;
|
|
15
18
|
let _amplitudeInitialized = false;
|
|
@@ -934,6 +937,9 @@ export function trackAgentChatLifecycle(input) {
|
|
|
934
937
|
})();
|
|
935
938
|
}
|
|
936
939
|
export function configureTracking(options) {
|
|
940
|
+
if (options.clientPlatform) {
|
|
941
|
+
_configuredAnalyticsClientPlatform = options.clientPlatform;
|
|
942
|
+
}
|
|
937
943
|
const publicKey = options.key || options.publicKey;
|
|
938
944
|
if (publicKey) {
|
|
939
945
|
_agentNativeAnalyticsPublicKey = publicKey;
|
|
@@ -1413,7 +1419,10 @@ function resolveProps(name, params) {
|
|
|
1413
1419
|
if (enriched[key] === undefined)
|
|
1414
1420
|
enriched[key] = value;
|
|
1415
1421
|
}
|
|
1416
|
-
return
|
|
1422
|
+
return {
|
|
1423
|
+
...applyTrackingIdentity(enriched),
|
|
1424
|
+
[ANALYTICS_CLIENT_PLATFORM_PROPERTY]: getAnalyticsClientPlatform(_configuredAnalyticsClientPlatform ?? undefined),
|
|
1425
|
+
};
|
|
1417
1426
|
}
|
|
1418
1427
|
function sessionReplayTrackingProperties() {
|
|
1419
1428
|
const module = _sessionReplayModuleForCapture;
|
|
@@ -11,6 +11,7 @@ export * from "./runtime.js";
|
|
|
11
11
|
export { sendToAgentChat, sendToAgentChatAndConfirm, reportAgentChatSubmitResult, AGENT_CHAT_SUBMIT_RESULT_EVENT, type AgentChatMessage, type AgentChatSubmitResult, type SendToAgentChatAndConfirmResult, } from "../agent-chat.js";
|
|
12
12
|
export { useAgentChatGenerating } from "../use-agent-chat.js";
|
|
13
13
|
export { useSendToAgentChat } from "../use-send-to-agent-chat.js";
|
|
14
|
+
export { DESKTOP_LOCAL_CODE_CHANGE_EVENT, requestDesktopLocalCodeChange, type DesktopLocalCodeChangeDetail, } from "../desktop-local-code-change.js";
|
|
14
15
|
export { AGENT_SIDEBAR_DEFAULT_MAX_WIDTH, AGENT_SIDEBAR_MIN_WIDTH, AGENT_SIDEBAR_WIDE_WIDTH_RATIO, clampAgentSidebarWidth, getAgentSidebarMaxWidth, getAgentSidebarWideWidth, requestAgentSidebarOpen, SIDEBAR_STATE_CHANGE_EVENT, setAgentSidebarOpenPreference, type AgentSidebarStateChangeDetail, type AgentSidebarStateMode, type AgentSidebarStateSource, } from "../agent-sidebar-state.js";
|
|
15
16
|
export { clearReservedToolRenderersForTests, clearToolRenderersForTests, registerActionChatRenderer, registerFallbackToolRenderer, registerReservedActionChatRenderer, registerReservedFallbackToolRenderer, registerReservedToolRenderer, registerToolRenderer, resolveToolRenderer, type ActionChatRendererRegistration, type ToolRendererComponent, type ToolRendererContext, type ToolRendererMatch, type ToolRendererProps, type ToolRendererRegistration, } from "./tool-render-registry.js";
|
|
16
17
|
export { ACTION_CHAT_UI_DATA_CHART_RENDERER, ACTION_CHAT_UI_DATA_INSIGHTS_RENDERER, ACTION_CHAT_UI_DATA_TABLE_RENDERER, ACTION_CHAT_UI_DATA_WIDGET_RENDERER, ACTION_CHAT_UI_INLINE_EXTENSION_RENDERER, ACTION_CHAT_UI_WORKSPACE_FILE_RENDERER, type ActionChatUIConfig, } from "../../action-ui.js";
|
|
@@ -11,6 +11,7 @@ export * from "./runtime.js";
|
|
|
11
11
|
export { sendToAgentChat, sendToAgentChatAndConfirm, reportAgentChatSubmitResult, AGENT_CHAT_SUBMIT_RESULT_EVENT, } from "../agent-chat.js";
|
|
12
12
|
export { useAgentChatGenerating } from "../use-agent-chat.js";
|
|
13
13
|
export { useSendToAgentChat } from "../use-send-to-agent-chat.js";
|
|
14
|
+
export { DESKTOP_LOCAL_CODE_CHANGE_EVENT, requestDesktopLocalCodeChange, } from "../desktop-local-code-change.js";
|
|
14
15
|
export { AGENT_SIDEBAR_DEFAULT_MAX_WIDTH, AGENT_SIDEBAR_MIN_WIDTH, AGENT_SIDEBAR_WIDE_WIDTH_RATIO, clampAgentSidebarWidth, getAgentSidebarMaxWidth, getAgentSidebarWideWidth, requestAgentSidebarOpen, SIDEBAR_STATE_CHANGE_EVENT, setAgentSidebarOpenPreference, } from "../agent-sidebar-state.js";
|
|
15
16
|
export { clearReservedToolRenderersForTests, clearToolRenderersForTests, registerActionChatRenderer, registerFallbackToolRenderer, registerReservedActionChatRenderer, registerReservedFallbackToolRenderer, registerReservedToolRenderer, registerToolRenderer, resolveToolRenderer, } from "./tool-render-registry.js";
|
|
16
17
|
export { ACTION_CHAT_UI_DATA_CHART_RENDERER, ACTION_CHAT_UI_DATA_INSIGHTS_RENDERER, ACTION_CHAT_UI_DATA_TABLE_RENDERER, ACTION_CHAT_UI_DATA_WIDGET_RENDERER, ACTION_CHAT_UI_INLINE_EXTENSION_RENDERER, ACTION_CHAT_UI_WORKSPACE_FILE_RENDERER, } from "../../action-ui.js";
|
|
@@ -33,9 +33,10 @@ export declare function BuilderSetupContent({ onConnected, layout, }: {
|
|
|
33
33
|
onConnected?: () => void;
|
|
34
34
|
layout?: BuilderSetupCardLayout;
|
|
35
35
|
}): import("react").JSX.Element;
|
|
36
|
-
export declare function BuilderSetupCard({ onConnected, bouncePulse, fullWidth, layout, }: {
|
|
36
|
+
export declare function BuilderSetupCard({ onConnected, bouncePulse, attached, fullWidth, layout, }: {
|
|
37
37
|
onConnected?: () => void;
|
|
38
38
|
bouncePulse?: number;
|
|
39
|
+
attached?: boolean;
|
|
39
40
|
fullWidth?: boolean;
|
|
40
41
|
layout?: BuilderSetupCardLayout;
|
|
41
42
|
}): import("react").JSX.Element;
|
|
@@ -165,7 +165,7 @@ export function BuilderSetupContent({ onConnected, layout = "default", }) {
|
|
|
165
165
|
defaultValue: "Custom keys",
|
|
166
166
|
}) })] })] }), keyOpen ? (_jsx("div", { className: "mt-3", children: _jsx(ApiKeyConnect, { onConnected: onConnected }) })) : null] }));
|
|
167
167
|
}
|
|
168
|
-
export function BuilderSetupCard({ onConnected, bouncePulse, fullWidth, layout = "default", }) {
|
|
168
|
+
export function BuilderSetupCard({ onConnected, bouncePulse, attached = false, fullWidth, layout = "default", }) {
|
|
169
169
|
const sidebarLayout = layout === "sidebar";
|
|
170
170
|
const cardRef = useRef(null);
|
|
171
171
|
// Replay the bounce keyframe each time bouncePulse increments. Toggling the
|
|
@@ -181,7 +181,7 @@ export function BuilderSetupCard({ onConnected, bouncePulse, fullWidth, layout =
|
|
|
181
181
|
void el.offsetWidth;
|
|
182
182
|
el.classList.add("animate-bounce-once");
|
|
183
183
|
}, [bouncePulse]);
|
|
184
|
-
return (_jsx("div", { ref: cardRef, className: cn("agent-builder-setup-card", sidebarLayout && "agent-builder-setup-card--sidebar", fullWidth
|
|
184
|
+
return (_jsx("div", { ref: cardRef, className: cn("agent-builder-setup-card", sidebarLayout && "agent-builder-setup-card--sidebar", attached && "agent-builder-setup-card--attached", fullWidth
|
|
185
185
|
? "w-full px-3 pb-2"
|
|
186
186
|
: sidebarLayout
|
|
187
187
|
? "mx-auto w-full max-w-[42rem] px-3 pb-2"
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import type { ChatFirstAppRailProps } from "./types.js";
|
|
2
|
-
export declare const ChatFirstAppsRail: import("react").MemoExoticComponent<({ apps, activeAppId, loading, error, collapsed, layout: controlledLayout, onLayoutChange, onLayoutError, onRetry, onOpenApp, onRemoveApp, onOpenAllApps, onCreateApp, createAppTrigger, renderIcon, copy, }: ChatFirstAppRailProps) => import("react").JSX.Element>;
|
|
2
|
+
export declare const ChatFirstAppsRail: import("react").MemoExoticComponent<({ apps, defaultAppIds, activeAppId, loading, error, collapsed, layout: controlledLayout, onLayoutChange, onLayoutError, onRetry, onOpenApp, onRemoveApp, onOpenAllApps, onCreateApp, createAppTrigger, renderIcon, copy, }: ChatFirstAppRailProps) => import("react").JSX.Element>;
|
|
@@ -2,7 +2,7 @@ import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-run
|
|
|
2
2
|
import { ContextMenu, ContextMenuContent, ContextMenuItem, ContextMenuSeparator, ContextMenuTrigger, Skeleton, Tooltip, TooltipContent, TooltipTrigger, } from "@agent-native/toolkit/ui";
|
|
3
3
|
import { IconApps, IconChevronDown, IconChevronUp, IconPin, IconPlus, IconTrash, } from "@tabler/icons-react";
|
|
4
4
|
import { memo, useMemo, useState } from "react";
|
|
5
|
-
import { orderChatFirstAppIds, readChatFirstAppLayout, writeChatFirstAppLayout, } from "../chat-first.js";
|
|
5
|
+
import { CHAT_FIRST_DEFAULT_APP_IDS, orderChatFirstAppIds, readChatFirstAppLayout, writeChatFirstAppLayout, } from "../chat-first.js";
|
|
6
6
|
import { cn } from "../utils.js";
|
|
7
7
|
import { defaultChatFirstCopy } from "./copy.js";
|
|
8
8
|
function ChatFirstRailAppIcon({ app, activeAppId, renderIcon, }) {
|
|
@@ -10,8 +10,8 @@ function ChatFirstRailAppIcon({ app, activeAppId, renderIcon, }) {
|
|
|
10
10
|
const isInactive = activeAppId !== undefined && !isActive;
|
|
11
11
|
return (_jsx("span", { "data-chat-first-app-icon": true, className: cn("transition-[filter]", isInactive && "grayscale"), children: renderIcon(app, { isActive, isInactive }) }));
|
|
12
12
|
}
|
|
13
|
-
function AppRows({ apps, activeAppId, layout, onDragStart, onDrop, onDragEnd, onOpenApp, onRemoveApp, onTogglePinned, onMove, renderIcon, copy, }) {
|
|
14
|
-
const orderedIds = orderChatFirstAppIds(apps.map((app) => app.id), layout);
|
|
13
|
+
function AppRows({ apps, defaultAppIds, activeAppId, layout, onDragStart, onDrop, onDragEnd, onOpenApp, onRemoveApp, onTogglePinned, onMove, renderIcon, copy, }) {
|
|
14
|
+
const orderedIds = orderChatFirstAppIds(apps.map((app) => app.id), layout, defaultAppIds);
|
|
15
15
|
const appsById = new Map(apps.map((app) => [app.id, app]));
|
|
16
16
|
const orderedApps = orderedIds
|
|
17
17
|
.map((id) => appsById.get(id))
|
|
@@ -41,28 +41,28 @@ function AppRows({ apps, activeAppId, layout, onDragStart, onDrop, onDragEnd, on
|
|
|
41
41
|
}), "aria-pressed": pinned, onClick: () => onTogglePinned(app.id), children: _jsx(IconPin, { size: 13, strokeWidth: pinned ? 2.2 : 1.6, "aria-hidden": "true" }) }), _jsx("span", { className: "sr-only", children: `${index + 1} of ${orderedApps.length}` })] }) }), _jsxs(ContextMenuContent, { children: [_jsxs(ContextMenuItem, { onSelect: () => onTogglePinned(app.id), children: [_jsx(IconPin, { size: 14, "aria-hidden": "true" }), pinned ? copy("removePinned") : copy("pinTop")] }), _jsx(ContextMenuSeparator, {}), _jsxs(ContextMenuItem, { disabled: index === 0, onSelect: () => onMove(app.id, -1), children: [_jsx(IconChevronUp, { size: 14, "aria-hidden": "true" }), copy("moveUp")] }), _jsxs(ContextMenuItem, { disabled: index === orderedApps.length - 1, onSelect: () => onMove(app.id, 1), children: [_jsx(IconChevronDown, { size: 14, "aria-hidden": "true" }), copy("moveDown")] }), onRemoveApp ? (_jsxs(_Fragment, { children: [_jsx(ContextMenuSeparator, {}), _jsxs(ContextMenuItem, { onSelect: () => onRemoveApp(app), className: "text-destructive focus:text-destructive", children: [_jsx(IconTrash, { size: 14, "aria-hidden": "true" }), copy("removeApp")] })] })) : null] })] }, app.id));
|
|
42
42
|
}) }));
|
|
43
43
|
}
|
|
44
|
-
export const ChatFirstAppsRail = memo(function ChatFirstAppsRail({ apps, activeAppId, loading = false, error, collapsed = false, layout: controlledLayout, onLayoutChange, onLayoutError, onRetry, onOpenApp, onRemoveApp, onOpenAllApps, onCreateApp, createAppTrigger, renderIcon, copy = defaultChatFirstCopy, }) {
|
|
44
|
+
export const ChatFirstAppsRail = memo(function ChatFirstAppsRail({ apps, defaultAppIds, activeAppId, loading = false, error, collapsed = false, layout: controlledLayout, onLayoutChange, onLayoutError, onRetry, onOpenApp, onRemoveApp, onOpenAllApps, onCreateApp, createAppTrigger, renderIcon, copy = defaultChatFirstCopy, }) {
|
|
45
45
|
const [localLayout, setLocalLayout] = useState(() => readChatFirstAppLayout());
|
|
46
46
|
const layout = controlledLayout ?? localLayout;
|
|
47
47
|
const [draggedAppId, setDraggedAppId] = useState(null);
|
|
48
48
|
const [showAllApps, setShowAllApps] = useState(false);
|
|
49
49
|
const orderedApps = useMemo(() => {
|
|
50
|
-
const orderedIds = orderChatFirstAppIds(apps.map((app) => app.id), layout);
|
|
50
|
+
const orderedIds = orderChatFirstAppIds(apps.map((app) => app.id), layout, defaultAppIds);
|
|
51
51
|
const appsById = new Map(apps.map((app) => [app.id, app]));
|
|
52
52
|
return orderedIds
|
|
53
53
|
.map((id) => appsById.get(id))
|
|
54
54
|
.filter((app) => Boolean(app));
|
|
55
|
-
}, [apps, layout]);
|
|
55
|
+
}, [apps, defaultAppIds, layout]);
|
|
56
56
|
const visibleApps = useMemo(() => {
|
|
57
57
|
if (showAllApps)
|
|
58
58
|
return orderedApps;
|
|
59
|
-
const defaultApps = orderedApps.slice(0,
|
|
59
|
+
const defaultApps = orderedApps.slice(0, defaultAppIds?.length ?? CHAT_FIRST_DEFAULT_APP_IDS.length);
|
|
60
60
|
if (!activeAppId || defaultApps.some((app) => app.id === activeAppId)) {
|
|
61
61
|
return defaultApps;
|
|
62
62
|
}
|
|
63
63
|
const activeApp = orderedApps.find((app) => app.id === activeAppId);
|
|
64
64
|
return activeApp ? [...defaultApps, activeApp] : defaultApps;
|
|
65
|
-
}, [activeAppId, orderedApps, showAllApps]);
|
|
65
|
+
}, [activeAppId, defaultAppIds, orderedApps, showAllApps]);
|
|
66
66
|
const hasMoreApps = orderedApps.length > visibleApps.length;
|
|
67
67
|
const createTrigger = createAppTrigger ??
|
|
68
68
|
(onCreateApp ? (_jsx("button", { type: "button", className: "flex size-6 items-center justify-center rounded text-sidebar-foreground/55 hover:bg-sidebar-accent hover:text-sidebar-foreground", onClick: onCreateApp, "aria-label": copy("createWorkspaceApp"), title: copy("createWorkspaceApp"), children: _jsx(IconPlus, { size: 14, "aria-hidden": "true" }) })) : null);
|
|
@@ -82,7 +82,7 @@ export const ChatFirstAppsRail = memo(function ChatFirstAppsRail({ apps, activeA
|
|
|
82
82
|
function reorderApps(targetId) {
|
|
83
83
|
if (!draggedAppId || draggedAppId === targetId)
|
|
84
84
|
return;
|
|
85
|
-
const currentOrder = orderChatFirstAppIds(apps.map((app) => app.id), layout);
|
|
85
|
+
const currentOrder = orderChatFirstAppIds(apps.map((app) => app.id), layout, defaultAppIds);
|
|
86
86
|
const fromIndex = currentOrder.indexOf(draggedAppId);
|
|
87
87
|
const toIndex = currentOrder.indexOf(targetId);
|
|
88
88
|
if (fromIndex < 0 || toIndex < 0)
|
|
@@ -94,7 +94,7 @@ export const ChatFirstAppsRail = memo(function ChatFirstAppsRail({ apps, activeA
|
|
|
94
94
|
setDraggedAppId(null);
|
|
95
95
|
}
|
|
96
96
|
function moveApp(appId, direction) {
|
|
97
|
-
const currentOrder = orderChatFirstAppIds(apps.map((app) => app.id), layout);
|
|
97
|
+
const currentOrder = orderChatFirstAppIds(apps.map((app) => app.id), layout, defaultAppIds);
|
|
98
98
|
const index = currentOrder.indexOf(appId);
|
|
99
99
|
const nextIndex = index + direction;
|
|
100
100
|
if (index < 0 || nextIndex < 0 || nextIndex >= currentOrder.length)
|
|
@@ -113,5 +113,5 @@ export const ChatFirstAppsRail = memo(function ChatFirstAppsRail({ apps, activeA
|
|
|
113
113
|
? "text-sidebar-foreground"
|
|
114
114
|
: "text-sidebar-foreground/70 hover:bg-sidebar-accent hover:text-sidebar-accent-foreground"), onClick: () => onOpenApp(app), "aria-label": copy("openApp", { name: app.name }), title: app.name, children: _jsx(ChatFirstRailAppIcon, { app: app, activeAppId: activeAppId, renderIcon: renderIcon }) }, app.id))), onOpenAllApps ? (_jsx("button", { type: "button", "data-chat-first-all-apps": true, className: "flex size-9 items-center justify-center rounded-md text-sidebar-foreground/70 hover:bg-sidebar-accent hover:text-sidebar-accent-foreground", onClick: onOpenAllApps, "aria-label": copy("allApps"), title: copy("allApps"), children: _jsx(IconApps, { size: 16, "aria-hidden": "true" }) })) : null, error ? (_jsx("span", { className: "size-1.5 rounded-full bg-destructive", title: error, "aria-label": error })) : null] }));
|
|
115
115
|
}
|
|
116
|
-
return (_jsxs("section", { "data-chat-first-apps-rail": true, className: "mt-3 px-2 pb-2 pt-2", "aria-label": copy("workspaceApps"), children: [_jsxs("div", { className: "mb-1 flex items-center gap-1.5 px-2 text-[11px] font-medium text-sidebar-foreground/50", children: [_jsx("span", { children: copy("workspaceApps") }), _jsx("span", { className: "ml-auto", children: createTrigger })] }), loading && apps.length === 0 ? (_jsx("div", { className: "space-y-0.5 px-2", children: [0, 1, 2].map((index) => (_jsx(Skeleton, { className: "h-8 w-full rounded-md" }, index))) })) : apps.length === 0 ? (_jsxs("div", { className: "px-2", children: [_jsx("p", { className: "text-xs text-sidebar-foreground/55", children: copy("noWorkspaceApps") }), createAppTrigger ? (createTrigger) : onCreateApp ? (_jsxs("button", { type: "button", className: "mt-1 inline-flex h-6 items-center gap-1.5 rounded-md border border-sidebar-border px-2 text-xs text-sidebar-foreground/75 hover:bg-sidebar-accent hover:text-sidebar-foreground", onClick: onCreateApp, children: [_jsx(IconPlus, { size: 13, "aria-hidden": "true" }), copy("createApp")] })) : (createTrigger)] })) : (_jsx(AppRows, { apps: visibleApps, activeAppId: activeAppId, layout: layout, onDragStart: setDraggedAppId, onDrop: reorderApps, onDragEnd: () => setDraggedAppId(null), onOpenApp: onOpenApp, onRemoveApp: onRemoveApp, onTogglePinned: togglePinned, onMove: moveApp, renderIcon: renderIcon, copy: copy })), hasMoreApps || showAllApps ? (_jsxs("button", { type: "button", className: "mt-0.5 flex h-8 w-full items-center gap-2 rounded-md px-2 text-xs text-sidebar-foreground/50 hover:bg-sidebar-accent hover:text-sidebar-foreground", onClick: () => setShowAllApps((value) => !value), children: [showAllApps ? (_jsx(IconChevronUp, { size: 14, "aria-hidden": "true" })) : (_jsx(IconChevronDown, { size: 14, "aria-hidden": "true" })), showAllApps ? copy("showLess") : copy("showMore")] })) : null, onOpenAllApps ? (_jsx("div", { className: "mt-1 border-t border-sidebar-border/60 pt-1", children: _jsxs("button", { type: "button", "data-chat-first-all-apps": true, className: "flex h-8 w-full items-center gap-2 rounded-md px-2 text-xs text-sidebar-foreground/55 hover:bg-sidebar-accent hover:text-sidebar-foreground", onClick: onOpenAllApps, children: [_jsx(IconApps, { size: 14, "aria-hidden": "true" }), _jsx("span", { children: copy("allApps") })] }) })) : null, error ? (_jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsxs("button", { type: "button", className: "mt-1 flex items-center gap-1 px-2 text-[10px] text-destructive/80", onClick: onRetry, "aria-label": error, children: [_jsx("span", { className: "size-1.5 rounded-full bg-destructive" }), onRetry ? copy("retry") : copy("appsLoadError")] }) }), _jsx(TooltipContent, { side: "right", children: error })] })) : null] }));
|
|
116
|
+
return (_jsxs("section", { "data-chat-first-apps-rail": true, className: "mt-3 px-2 pb-2 pt-2", "aria-label": copy("workspaceApps"), children: [_jsxs("div", { className: "mb-1 flex items-center gap-1.5 px-2 text-[11px] font-medium text-sidebar-foreground/50", children: [_jsx("span", { children: copy("workspaceApps") }), _jsx("span", { className: "ml-auto", children: createTrigger })] }), loading && apps.length === 0 ? (_jsx("div", { className: "space-y-0.5 px-2", children: [0, 1, 2].map((index) => (_jsx(Skeleton, { className: "h-8 w-full rounded-md" }, index))) })) : apps.length === 0 ? (_jsxs("div", { className: "px-2", children: [_jsx("p", { className: "text-xs text-sidebar-foreground/55", children: copy("noWorkspaceApps") }), createAppTrigger ? (createTrigger) : onCreateApp ? (_jsxs("button", { type: "button", className: "mt-1 inline-flex h-6 items-center gap-1.5 rounded-md border border-sidebar-border px-2 text-xs text-sidebar-foreground/75 hover:bg-sidebar-accent hover:text-sidebar-foreground", onClick: onCreateApp, children: [_jsx(IconPlus, { size: 13, "aria-hidden": "true" }), copy("createApp")] })) : (createTrigger)] })) : (_jsx(AppRows, { apps: visibleApps, defaultAppIds: defaultAppIds, activeAppId: activeAppId, layout: layout, onDragStart: setDraggedAppId, onDrop: reorderApps, onDragEnd: () => setDraggedAppId(null), onOpenApp: onOpenApp, onRemoveApp: onRemoveApp, onTogglePinned: togglePinned, onMove: moveApp, renderIcon: renderIcon, copy: copy })), hasMoreApps || showAllApps ? (_jsxs("button", { type: "button", className: "mt-0.5 flex h-8 w-full items-center gap-2 rounded-md px-2 text-xs text-sidebar-foreground/50 hover:bg-sidebar-accent hover:text-sidebar-foreground", onClick: () => setShowAllApps((value) => !value), children: [showAllApps ? (_jsx(IconChevronUp, { size: 14, "aria-hidden": "true" })) : (_jsx(IconChevronDown, { size: 14, "aria-hidden": "true" })), showAllApps ? copy("showLess") : copy("showMore")] })) : null, onOpenAllApps ? (_jsx("div", { className: "mt-1 border-t border-sidebar-border/60 pt-1", children: _jsxs("button", { type: "button", "data-chat-first-all-apps": true, className: "flex h-8 w-full items-center gap-2 rounded-md px-2 text-xs text-sidebar-foreground/55 hover:bg-sidebar-accent hover:text-sidebar-foreground", onClick: onOpenAllApps, children: [_jsx(IconApps, { size: 14, "aria-hidden": "true" }), _jsx("span", { children: copy("allApps") })] }) })) : null, error ? (_jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsxs("button", { type: "button", className: "mt-1 flex items-center gap-1 px-2 text-[10px] text-destructive/80", onClick: onRetry, "aria-label": error, children: [_jsx("span", { className: "size-1.5 rounded-full bg-destructive" }), onRetry ? copy("retry") : copy("appsLoadError")] }) }), _jsx(TooltipContent, { side: "right", children: error })] })) : null] }));
|
|
117
117
|
});
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { ReactNode } from "react";
|
|
2
2
|
import { type ChatFirstSurfaceTab } from "../chat-first.js";
|
|
3
3
|
import type { ChatFirstSurfaceTabsProps } from "./types.js";
|
|
4
|
-
export declare function ChatFirstSurfaceTabs({ tabs, activeTabId, onActivate, onClose, onCloseOthers, onCloseToRight, onCloseAll, onOpenSurface, apps, onOpenApp, renderAppIcon, copy, }: ChatFirstSurfaceTabsProps): import("react").JSX.Element;
|
|
4
|
+
export declare function ChatFirstSurfaceTabs({ tabs, activeTabId, onActivate, onClose, onCloseOthers, onCloseToRight, onCloseAll, onOpenSurface, hiddenSurfaceKinds, apps, onOpenApp, renderAppIcon, onAddTab, addTabLabel, copy, }: ChatFirstSurfaceTabsProps): import("react").JSX.Element;
|
|
5
5
|
export declare function ChatFirstSurfaceContent({ tabs, activeTabId, renderTab, }: {
|
|
6
6
|
tabs: readonly ChatFirstSurfaceTab[];
|
|
7
7
|
activeTabId: string | null;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { ContextMenu, ContextMenuContent, ContextMenuItem, ContextMenuSeparator, ContextMenuTrigger, Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, } from "@agent-native/toolkit/ui";
|
|
3
|
-
import { IconFiles, IconGitCompare, IconMessageCircle, IconTerminal2, IconUsersGroup, IconWorld, IconX, } from "@tabler/icons-react";
|
|
3
|
+
import { IconFiles, IconGitCompare, IconMessageCircle, IconPlus, IconTerminal2, IconUsersGroup, IconWorld, IconX, } from "@tabler/icons-react";
|
|
4
4
|
import { CHAT_FIRST_SURFACE_CATALOG, } from "../chat-first.js";
|
|
5
5
|
import { cn } from "../utils.js";
|
|
6
6
|
import { defaultChatFirstCopy } from "./copy.js";
|
|
@@ -17,44 +17,44 @@ function SurfaceIcon({ kind }) {
|
|
|
17
17
|
const Icon = ICONS[kind];
|
|
18
18
|
return _jsx(Icon, { size: 14, "aria-hidden": "true" });
|
|
19
19
|
}
|
|
20
|
-
export function ChatFirstSurfaceTabs({ tabs, activeTabId, onActivate, onClose, onCloseOthers, onCloseToRight, onCloseAll, onOpenSurface, apps = [], onOpenApp, renderAppIcon, copy = defaultChatFirstCopy, }) {
|
|
20
|
+
export function ChatFirstSurfaceTabs({ tabs, activeTabId, onActivate, onClose, onCloseOthers, onCloseToRight, onCloseAll, onOpenSurface, hiddenSurfaceKinds = [], apps = [], onOpenApp, renderAppIcon, onAddTab, addTabLabel = "New tab", copy = defaultChatFirstCopy, }) {
|
|
21
21
|
return (_jsx(TooltipProvider, { delayDuration: 400, children: _jsx("div", { "data-chat-first-surface-tabs": true, className: cn("min-w-0 border-b border-border bg-card", tabs.length > 0
|
|
22
22
|
? "shrink-0"
|
|
23
|
-
: "flex min-h-0 min-w-0 flex-1 flex-col overflow-hidden"), children: tabs.length > 0 ? (
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
event.preventDefault();
|
|
28
|
-
onClose(tab);
|
|
29
|
-
}
|
|
30
|
-
}, title: tab.title, children: [_jsxs("button", { type: "button", role: "tab", tabIndex: activeTabId === tab.id ? 0 : -1, "aria-selected": activeTabId === tab.id, "data-chat-first-surface-tab-id": tab.id, className: "flex min-w-0 flex-1 items-center gap-1.5 truncate rounded-md px-2 text-start focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring", onKeyDown: (event) => {
|
|
31
|
-
if (event.key === "Enter" || event.key === " ") {
|
|
32
|
-
event.preventDefault();
|
|
33
|
-
onActivate(tab);
|
|
34
|
-
return;
|
|
35
|
-
}
|
|
36
|
-
const nextIndex = event.key === "ArrowRight"
|
|
37
|
-
? (index + 1) % tabs.length
|
|
38
|
-
: event.key === "ArrowLeft"
|
|
39
|
-
? (index - 1 + tabs.length) % tabs.length
|
|
40
|
-
: event.key === "Home"
|
|
41
|
-
? 0
|
|
42
|
-
: event.key === "End"
|
|
43
|
-
? tabs.length - 1
|
|
44
|
-
: -1;
|
|
45
|
-
if (nextIndex < 0)
|
|
46
|
-
return;
|
|
23
|
+
: "flex min-h-0 min-w-0 flex-1 flex-col overflow-hidden"), children: tabs.length > 0 ? (_jsxs("div", { className: "flex min-w-0 items-center gap-1 overflow-x-auto px-2 py-1.5", role: "tablist", "aria-label": copy("openSideSurfaces"), children: [tabs.map((tab, index) => (_jsxs(ContextMenu, { children: [_jsx(ContextMenuTrigger, { asChild: true, children: _jsxs("div", { "data-surface-tab-id": tab.id, "data-active": activeTabId === tab.id ? "true" : "false", className: cn("group flex h-8 min-w-0 max-w-48 shrink-0 items-center rounded-md text-xs transition-colors", activeTabId === tab.id
|
|
24
|
+
? "bg-accent text-foreground"
|
|
25
|
+
: "text-muted-foreground hover:bg-accent hover:text-foreground"), onMouseDown: (event) => {
|
|
26
|
+
if (event.button === 1) {
|
|
47
27
|
event.preventDefault();
|
|
48
|
-
onActivate(tabs[nextIndex]);
|
|
49
|
-
requestAnimationFrame(() => {
|
|
50
|
-
document
|
|
51
|
-
.querySelector(`[data-chat-first-surface-tab-id="${CSS.escape(tabs[nextIndex].id)}"]`)
|
|
52
|
-
?.focus();
|
|
53
|
-
});
|
|
54
|
-
}, onClick: () => onActivate(tab), children: [_jsx(SurfaceIcon, { kind: tab.kind }), _jsx("span", { className: "truncate", children: tab.title })] }), _jsx("button", { type: "button", className: "mr-1 flex size-5 shrink-0 items-center justify-center rounded text-muted-foreground/65 opacity-0 transition-opacity hover:bg-background/70 hover:text-foreground group-hover:opacity-100 focus-visible:opacity-100", "aria-label": copy("closeTab", { name: tab.title }), title: copy("closeTab", { name: tab.title }), onClick: (event) => {
|
|
55
|
-
event.stopPropagation();
|
|
56
28
|
onClose(tab);
|
|
57
|
-
}
|
|
29
|
+
}
|
|
30
|
+
}, title: tab.title, children: [_jsxs("button", { type: "button", role: "tab", tabIndex: activeTabId === tab.id ? 0 : -1, "aria-selected": activeTabId === tab.id, "data-chat-first-surface-tab-id": tab.id, className: "flex min-w-0 flex-1 items-center gap-1.5 truncate rounded-md px-2 text-start focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring", onKeyDown: (event) => {
|
|
31
|
+
if (event.key === "Enter" || event.key === " ") {
|
|
32
|
+
event.preventDefault();
|
|
33
|
+
onActivate(tab);
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
const nextIndex = event.key === "ArrowRight"
|
|
37
|
+
? (index + 1) % tabs.length
|
|
38
|
+
: event.key === "ArrowLeft"
|
|
39
|
+
? (index - 1 + tabs.length) % tabs.length
|
|
40
|
+
: event.key === "Home"
|
|
41
|
+
? 0
|
|
42
|
+
: event.key === "End"
|
|
43
|
+
? tabs.length - 1
|
|
44
|
+
: -1;
|
|
45
|
+
if (nextIndex < 0)
|
|
46
|
+
return;
|
|
47
|
+
event.preventDefault();
|
|
48
|
+
onActivate(tabs[nextIndex]);
|
|
49
|
+
requestAnimationFrame(() => {
|
|
50
|
+
document
|
|
51
|
+
.querySelector(`[data-chat-first-surface-tab-id="${CSS.escape(tabs[nextIndex].id)}"]`)
|
|
52
|
+
?.focus();
|
|
53
|
+
});
|
|
54
|
+
}, onClick: () => onActivate(tab), children: [_jsx(SurfaceIcon, { kind: tab.kind }), _jsx("span", { className: "truncate", children: tab.title })] }), _jsx("button", { type: "button", className: "mr-1 flex size-5 shrink-0 items-center justify-center rounded text-muted-foreground/65 opacity-0 transition-opacity hover:bg-background/70 hover:text-foreground group-hover:opacity-100 focus-visible:opacity-100", "aria-label": copy("closeTab", { name: tab.title }), title: copy("closeTab", { name: tab.title }), onClick: (event) => {
|
|
55
|
+
event.stopPropagation();
|
|
56
|
+
onClose(tab);
|
|
57
|
+
}, children: _jsx(IconX, { size: 12, "aria-hidden": "true" }) })] }) }), _jsxs(ContextMenuContent, { children: [_jsx(ContextMenuItem, { onSelect: () => onClose(tab), children: copy("close") }), _jsx(ContextMenuItem, { disabled: tabs.length < 2, onSelect: () => onCloseOthers(tab), children: copy("closeOthers") }), _jsx(ContextMenuItem, { disabled: tabs[tabs.length - 1]?.id === tab.id, onSelect: () => onCloseToRight(tab), children: copy("closeToRight") }), _jsx(ContextMenuSeparator, {}), _jsx(ContextMenuItem, { onSelect: onCloseAll, children: copy("closeAll") })] })] }, tab.id))), onAddTab ? (_jsx("button", { type: "button", className: "flex size-8 shrink-0 items-center justify-center rounded-md text-muted-foreground/65 transition-colors hover:bg-accent hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring", "aria-label": addTabLabel, title: addTabLabel, onClick: onAddTab, children: _jsx(IconPlus, { size: 14, "aria-hidden": "true" }) })) : null] })) : (_jsxs("div", { className: "flex min-h-0 min-w-0 flex-1 flex-col overflow-y-auto px-2 py-1", "data-surface-empty-state": true, "aria-label": copy("openSideSurfaces"), children: [CHAT_FIRST_SURFACE_CATALOG.filter((surface) => !hiddenSurfaceKinds.includes(surface.kind)).map((surface) => {
|
|
58
58
|
const label = copy(`surface.${surface.kind}.label`);
|
|
59
59
|
const reason = surface.availability === "deferred"
|
|
60
60
|
? copy(`surface.${surface.kind}.reason`)
|
|
@@ -62,6 +62,8 @@ export function ChatFirstSurfaceTabs({ tabs, activeTabId, onActivate, onClose, o
|
|
|
62
62
|
const isDeferred = surface.availability === "deferred";
|
|
63
63
|
const canOpenSurface = onOpenSurface &&
|
|
64
64
|
(surface.kind === "browser" ||
|
|
65
|
+
(surface.kind === "terminal" &&
|
|
66
|
+
surface.availability === "desktop") ||
|
|
65
67
|
surface.kind === "side-chat" ||
|
|
66
68
|
surface.kind === "agents");
|
|
67
69
|
const row = (_jsxs("div", { className: cn("flex h-7 min-w-0 items-center gap-2 rounded px-2 text-xs transition-colors", canOpenSurface
|
|
@@ -78,7 +80,7 @@ export function ChatFirstSurfaceTabs({ tabs, activeTabId, onActivate, onClose, o
|
|
|
78
80
|
}), apps.length > 0 && onOpenApp ? (_jsxs("div", { className: "mt-1 border-t border-border pt-1", children: [_jsx("p", { className: "px-2 py-1 text-[10px] font-medium uppercase tracking-wide text-muted-foreground", children: copy("workspaceApps") }), _jsx("div", { className: "space-y-0.5", children: apps.map((app) => (_jsxs("button", { type: "button", "data-chat-first-surface-app": app.id, className: "flex h-8 w-full min-w-0 items-center gap-2 rounded px-2 text-start text-xs text-foreground transition-colors hover:bg-accent", title: copy("openApp", { name: app.name }), "aria-label": copy("openApp", { name: app.name }), onClick: () => onOpenApp(app), children: [renderAppIcon?.(app) ?? _jsx(SurfaceIcon, { kind: "app" }), _jsx("span", { className: "min-w-0 flex-1 truncate", children: app.name })] }, app.id))) })] })) : null] })) }) }));
|
|
79
81
|
}
|
|
80
82
|
export function ChatFirstSurfaceContent({ tabs, activeTabId, renderTab, }) {
|
|
81
|
-
return (_jsx("div", { className: "min-h-0 flex-1 overflow-hidden", children: tabs.map((tab) => {
|
|
83
|
+
return (_jsx("div", { className: "flex h-full min-h-0 flex-1 flex-col overflow-hidden", children: tabs.map((tab) => {
|
|
82
84
|
const active = tab.id === activeTabId;
|
|
83
85
|
return (_jsx("div", { "data-chat-first-surface-content": tab.id, "aria-hidden": !active, className: cn("h-full min-h-0", !active && "hidden"), children: renderTab(tab) }, tab.id));
|
|
84
86
|
}) }));
|
|
@@ -35,6 +35,9 @@ export interface ChatFirstSurfaceTabsProps {
|
|
|
35
35
|
onCloseToRight: (tab: ChatFirstSurfaceTab) => void;
|
|
36
36
|
onCloseAll: () => void;
|
|
37
37
|
onOpenSurface?: (kind: ChatFirstSurfaceKind) => void;
|
|
38
|
+
hiddenSurfaceKinds?: readonly ChatFirstSurfaceKind[];
|
|
39
|
+
onAddTab?: () => void;
|
|
40
|
+
addTabLabel?: string;
|
|
38
41
|
apps?: readonly ChatFirstAppItem[];
|
|
39
42
|
onOpenApp?: (app: ChatFirstAppItem) => void;
|
|
40
43
|
renderAppIcon?: (app: ChatFirstAppItem) => ReactNode;
|
|
@@ -42,6 +45,8 @@ export interface ChatFirstSurfaceTabsProps {
|
|
|
42
45
|
}
|
|
43
46
|
export interface ChatFirstAppRailProps {
|
|
44
47
|
apps: readonly ChatFirstAppItem[];
|
|
48
|
+
/** Optional host-specific fallback order for apps without a saved layout. */
|
|
49
|
+
defaultAppIds?: readonly string[];
|
|
45
50
|
activeAppId?: string;
|
|
46
51
|
loading?: boolean;
|
|
47
52
|
error?: string | null;
|
|
@@ -188,7 +188,7 @@ export declare function writeChatFirstAppLayout(layout: ChatFirstAppLayoutPrefer
|
|
|
188
188
|
ok: false;
|
|
189
189
|
reason: "unavailable" | "write-failed";
|
|
190
190
|
};
|
|
191
|
-
export declare function orderChatFirstAppIds(appIds: readonly string[], layout: ChatFirstAppLayoutPreference): string[];
|
|
191
|
+
export declare function orderChatFirstAppIds(appIds: readonly string[], layout: ChatFirstAppLayoutPreference, preferredAppIds?: readonly string[]): string[];
|
|
192
192
|
export declare function resolveChatFirstBrowserTarget(detail: ChatFirstOpenBrowserDetail): ChatFirstBrowserResolution;
|
|
193
193
|
type ChatFirstOpenAppListener = (detail: ChatFirstOpenAppDetail) => void;
|
|
194
194
|
type ChatFirstOpenBrowserListener = (detail: ChatFirstOpenBrowserDetail) => void;
|
|
@@ -19,8 +19,8 @@ export const CHAT_FIRST_SURFACE_CATALOG = [
|
|
|
19
19
|
kind: "terminal",
|
|
20
20
|
label: "Terminal",
|
|
21
21
|
description: "Run commands beside the conversation.",
|
|
22
|
-
availability: "
|
|
23
|
-
disabledReason: "
|
|
22
|
+
availability: "desktop",
|
|
23
|
+
disabledReason: "Open a local coding-agent terminal beside the conversation.",
|
|
24
24
|
},
|
|
25
25
|
{
|
|
26
26
|
kind: "files",
|
|
@@ -304,9 +304,9 @@ export function writeChatFirstAppLayout(layout, storage = browserStorage()) {
|
|
|
304
304
|
return { ok: false, reason: "write-failed" };
|
|
305
305
|
}
|
|
306
306
|
}
|
|
307
|
-
export function orderChatFirstAppIds(appIds, layout) {
|
|
307
|
+
export function orderChatFirstAppIds(appIds, layout, preferredAppIds = CHAT_FIRST_DEFAULT_APP_IDS) {
|
|
308
308
|
const available = new Set(appIds);
|
|
309
|
-
const preferredDefaults =
|
|
309
|
+
const preferredDefaults = preferredAppIds.filter((id) => available.has(id));
|
|
310
310
|
const preferredDefaultSet = new Set(preferredDefaults);
|
|
311
311
|
const fallbackOrder = [
|
|
312
312
|
...preferredDefaults,
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export declare const DESKTOP_LOCAL_CODE_CHANGE_EVENT = "agent-native:desktop-local-code-change";
|
|
2
|
+
export interface DesktopLocalCodeChangeDetail {
|
|
3
|
+
prompt: string;
|
|
4
|
+
}
|
|
5
|
+
/**
|
|
6
|
+
* Ask an embedding desktop shell to prepare a local code-change workspace.
|
|
7
|
+
* The optional target keeps bubbling events scoped to the shell that owns the
|
|
8
|
+
* chat card while preserving a window fallback for standalone consumers.
|
|
9
|
+
*/
|
|
10
|
+
export declare function requestDesktopLocalCodeChange(prompt: string, target?: EventTarget | null): boolean;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export const DESKTOP_LOCAL_CODE_CHANGE_EVENT = "agent-native:desktop-local-code-change";
|
|
2
|
+
/**
|
|
3
|
+
* Ask an embedding desktop shell to prepare a local code-change workspace.
|
|
4
|
+
* The optional target keeps bubbling events scoped to the shell that owns the
|
|
5
|
+
* chat card while preserving a window fallback for standalone consumers.
|
|
6
|
+
*/
|
|
7
|
+
export function requestDesktopLocalCodeChange(prompt, target = typeof window === "undefined" ? null : window) {
|
|
8
|
+
const trimmed = prompt.trim();
|
|
9
|
+
if (!trimmed || !target)
|
|
10
|
+
return false;
|
|
11
|
+
target.dispatchEvent(new CustomEvent(DESKTOP_LOCAL_CODE_CHANGE_EVENT, {
|
|
12
|
+
bubbles: true,
|
|
13
|
+
detail: { prompt: trimmed },
|
|
14
|
+
}));
|
|
15
|
+
return true;
|
|
16
|
+
}
|
package/dist/client/index.d.ts
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
* Compatibility aggregation only; new code must not import this barrel.
|
|
4
4
|
*/
|
|
5
5
|
export * from "./agent-chat/index.js";
|
|
6
|
+
export * from "./desktop-local-code-change.js";
|
|
6
7
|
export * from "./hooks/index.js";
|
|
7
8
|
export * from "./navigation/index.js";
|
|
8
9
|
export * from "./host/index.js";
|
package/dist/client/index.js
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
* Compatibility aggregation only; new code must not import this barrel.
|
|
4
4
|
*/
|
|
5
5
|
export * from "./agent-chat/index.js";
|
|
6
|
+
export * from "./desktop-local-code-change.js";
|
|
6
7
|
export * from "./hooks/index.js";
|
|
7
8
|
export * from "./navigation/index.js";
|
|
8
9
|
export * from "./host/index.js";
|
|
@@ -16,7 +16,7 @@ export function ThumbsFeedback({ threadId, runId, messageSeq, className, }) {
|
|
|
16
16
|
const feedbackInputRef = useRef(null);
|
|
17
17
|
const sendFeedback = useCallback(async (feedbackType, value) => {
|
|
18
18
|
try {
|
|
19
|
-
await fetch(agentNativePath("/_agent-native/observability/feedback"), {
|
|
19
|
+
const response = await fetch(agentNativePath("/_agent-native/observability/feedback"), {
|
|
20
20
|
method: "POST",
|
|
21
21
|
headers: { "Content-Type": "application/json" },
|
|
22
22
|
body: JSON.stringify({
|
|
@@ -27,9 +27,14 @@ export function ThumbsFeedback({ threadId, runId, messageSeq, className, }) {
|
|
|
27
27
|
value: value ?? "",
|
|
28
28
|
}),
|
|
29
29
|
});
|
|
30
|
+
if (!response.ok) {
|
|
31
|
+
throw new Error(`Feedback submission failed (${response.status})`);
|
|
32
|
+
}
|
|
33
|
+
return true;
|
|
30
34
|
}
|
|
31
35
|
catch {
|
|
32
|
-
//
|
|
36
|
+
// coercion-ok: callers receive false and restore the retryable UI state.
|
|
37
|
+
return false;
|
|
33
38
|
}
|
|
34
39
|
}, [threadId, runId, messageSeq]);
|
|
35
40
|
const handleThumbsUp = useCallback(() => {
|
|
@@ -37,7 +42,10 @@ export function ThumbsFeedback({ threadId, runId, messageSeq, className, }) {
|
|
|
37
42
|
return;
|
|
38
43
|
setSelection("up");
|
|
39
44
|
setPopoverOpen(false);
|
|
40
|
-
sendFeedback("thumbs_up")
|
|
45
|
+
void sendFeedback("thumbs_up").then((submitted) => {
|
|
46
|
+
if (!submitted)
|
|
47
|
+
setSelection(null);
|
|
48
|
+
});
|
|
41
49
|
}, [selection, sendFeedback]);
|
|
42
50
|
const handleThumbsDown = useCallback(() => {
|
|
43
51
|
if (selection === "down") {
|
|
@@ -46,15 +54,21 @@ export function ThumbsFeedback({ threadId, runId, messageSeq, className, }) {
|
|
|
46
54
|
}
|
|
47
55
|
setSelection("down");
|
|
48
56
|
setPopoverOpen(true);
|
|
49
|
-
sendFeedback("thumbs_down")
|
|
57
|
+
void sendFeedback("thumbs_down").then((submitted) => {
|
|
58
|
+
if (!submitted)
|
|
59
|
+
setSelection(null);
|
|
60
|
+
});
|
|
50
61
|
}, [selection, sendFeedback]);
|
|
51
62
|
const handleTextFeedback = useCallback(() => {
|
|
52
63
|
const value = textFeedback.trim();
|
|
53
64
|
if (!value)
|
|
54
65
|
return;
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
66
|
+
void sendFeedback("text", value).then((submitted) => {
|
|
67
|
+
if (!submitted)
|
|
68
|
+
return;
|
|
69
|
+
setTextFeedback("");
|
|
70
|
+
setPopoverOpen(false);
|
|
71
|
+
});
|
|
58
72
|
}, [sendFeedback, textFeedback]);
|
|
59
73
|
return (_jsxs("div", { className: cn("inline-flex items-center gap-0.5", className), children: [_jsx("button", { type: "button", "aria-label": t("agentChat.feedback.thumbsUp"), onClick: handleThumbsUp, className: cn("flex h-6 w-6 items-center justify-center rounded", selection === "up"
|
|
60
74
|
? "text-foreground"
|
|
@@ -30,6 +30,14 @@ export interface AgentTerminalProps {
|
|
|
30
30
|
onConnectionChange?: (connected: boolean) => void;
|
|
31
31
|
/** Callback when agent running state changes */
|
|
32
32
|
onAgentRunningChange?: (running: boolean) => void;
|
|
33
|
+
/** Queue a prompt for the CLI once the PTY WebSocket is ready. */
|
|
34
|
+
submitRequest?: AgentTerminalSubmitRequest;
|
|
35
|
+
/** Called after a queued prompt is written to the PTY. */
|
|
36
|
+
onPromptSubmitted?: (request: AgentTerminalSubmitRequest) => void;
|
|
37
|
+
}
|
|
38
|
+
export interface AgentTerminalSubmitRequest {
|
|
39
|
+
id: string | number;
|
|
40
|
+
text: string;
|
|
33
41
|
}
|
|
34
42
|
export declare function formatWebSocketHostname(hostname: string): string;
|
|
35
|
-
export declare function AgentTerminal({ command, flags, wsUrl: wsUrlProp, hideInFrame, theme, fontSize, className, style, onConnectionChange, onAgentRunningChange, }: AgentTerminalProps): import("react").JSX.Element | null;
|
|
43
|
+
export declare function AgentTerminal({ command, flags, wsUrl: wsUrlProp, hideInFrame, theme, fontSize, className, style, onConnectionChange, onAgentRunningChange, submitRequest, onPromptSubmitted, }: AgentTerminalProps): import("react").JSX.Element | null;
|