@agent-native/core 0.153.10 → 0.154.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/corpus/README.md +1 -1
- package/corpus/templates/analytics/AGENTS.md +20 -30
- package/corpus/templates/analytics/actions/search-dashboard-references.ts +58 -0
- package/corpus/templates/analytics/app/components/layout/Sidebar.tsx +1 -1
- package/corpus/templates/analytics/app/lib/utils.ts +1 -1
- package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/ViewSqlPopover.tsx +1 -1
- package/corpus/templates/analytics/server/lib/agent-chat-plan-mode.ts +2 -0
- package/corpus/templates/analytics/server/lib/dashboards-store.ts +366 -3
- package/corpus/templates/analytics/server/lib/real-data-actions.ts +3 -1
- package/corpus/templates/analytics/server/plugins/agent-chat.ts +6 -2
- package/corpus/templates/calendar/app/components/calendar/EventDialog.tsx +1 -1
- package/corpus/templates/calendar/app/lib/utils.ts +1 -1
- package/corpus/templates/clips/app/components/recorder/recorder-engine.ts +32 -5
- package/corpus/templates/clips/app/components/sharing/share-ui.tsx +15 -15
- package/corpus/templates/clips/app/i18n/en-US.ts +3 -3
- package/corpus/templates/clips/app/lib/utils.ts +5 -6
- package/corpus/templates/clips/chrome-extension/src/offscreen.ts +43 -8
- package/corpus/templates/clips/desktop/src/app.tsx +26 -12
- package/corpus/templates/clips/desktop/src/lib/recorder.ts +23 -9
- package/corpus/templates/clips/desktop/src-tauri/src/native_screen/custom_capture.rs +261 -11
- package/corpus/templates/clips/desktop/src-tauri/src/native_screen.rs +21 -3
- package/corpus/templates/clips/shared/mic-audio-cleanup.ts +350 -0
- package/corpus/templates/content/actions/resolve-content-landing.ts +162 -32
- package/corpus/templates/content/app/i18n-data.ts +10 -10
- package/corpus/templates/content/scripts/check-native-deps.mjs +181 -15
- package/corpus/templates/content/shared/content-landing.ts +5 -0
- package/corpus/templates/design/.agents/skills/design-generation/SKILL.md +79 -7
- package/corpus/templates/design/.agents/skills/design-systems/SKILL.md +14 -2
- package/corpus/templates/design/.agents/skills/visual-edit/SKILL.md +2 -2
- package/corpus/templates/design/.generated/bridge/editor-chrome.generated.ts +35 -11
- package/corpus/templates/design/actions/get-design-system.ts +103 -3
- package/corpus/templates/design/actions/import-design-tokens.ts +37 -8
- package/corpus/templates/design/actions/import-github.ts +32 -138
- package/corpus/templates/design/actions/index-design-system-with-builder.ts +49 -16
- package/corpus/templates/design/actions/present-design-variants.ts +93 -4
- package/corpus/templates/design/actions/run-design-audit.ts +229 -0
- package/corpus/templates/design/actions/sync-design-system-with-builder.ts +64 -0
- package/corpus/templates/design/app/components/design/code-workbench/commands.ts +2 -2
- package/corpus/templates/design/app/components/design/inspector/DesignColorPicker.tsx +17 -4
- package/corpus/templates/design/app/components/design/inspector/GradientEditor.tsx +5 -1
- package/corpus/templates/design/app/components/design/inspector/ImageFillControls.tsx +5 -1
- package/corpus/templates/design/app/hooks/use-question-flow.ts +81 -5
- package/corpus/templates/design/app/i18n/en-US.ts +1 -1
- package/corpus/templates/design/app/i18n-data.ts +32 -1
- package/corpus/templates/design/app/i18n-keyboard-shortcuts.ts +10 -10
- package/corpus/templates/design/app/pages/DesignSystemSetup.tsx +83 -11
- package/corpus/templates/design/app/pages/DesignSystems.tsx +14 -0
- package/corpus/templates/design/app/pages/design-editor/generation-prompt-directives.ts +22 -0
- package/corpus/templates/design/changelog/2026-08-13-a-screen-that-would-render-behind-an-invisible-alpine-overla.md +6 -0
- package/corpus/templates/design/changelog/2026-08-13-attach-a-ui-screenshot-and-the-design-is-reproduced-not-rein.md +6 -0
- package/corpus/templates/design/changelog/2026-08-13-linking-a-design-system-means-you-never-get-generic-directio.md +6 -0
- package/corpus/templates/design/changelog/2026-08-13-the-design-audit-now-reports-when-a-screen-ignores-its-linke.md +6 -0
- package/corpus/templates/design/changelog/2026-08-13-the-design-system-preview-now-shows-how-many-named-tokens-we.md +6 -0
- package/corpus/templates/design/changelog/2026-08-13-your-design-system-prompt-and-reference-screenshots-now-reac.md +6 -0
- package/corpus/templates/design/server/lib/builder-design-system-proxy.ts +18 -2
- package/corpus/templates/design/shared/design-review.ts +1 -0
- package/corpus/templates/design/shared/html-integrity.ts +171 -0
- package/corpus/templates/mail/app/lib/utils.ts +1 -1
- package/corpus/templates/slides/.agents/skills/design-systems/SKILL.md +10 -6
- package/corpus/templates/slides/actions/index-design-system-with-builder.ts +41 -3
- package/corpus/templates/slides/actions/patch-deck.ts +12 -3
- package/corpus/templates/slides/actions/sync-design-system-with-builder.ts +64 -0
- package/corpus/templates/slides/app/components/deck/DeckCard.tsx +1 -1
- package/corpus/templates/slides/app/components/design-system/DesignSystemSetup.tsx +193 -20
- package/corpus/templates/slides/app/components/editor/EditorActionCluster.tsx +73 -1
- package/corpus/templates/slides/app/components/editor/EditorSidebar.tsx +64 -34
- package/corpus/templates/slides/app/components/editor/EditorToolbar.tsx +34 -41
- package/corpus/templates/slides/app/components/editor/ExportMenu.tsx +119 -91
- package/corpus/templates/slides/app/components/editor/ImageOverlay.tsx +16 -0
- package/corpus/templates/slides/app/components/editor/NewDeckReferenceStep.tsx +15 -0
- package/corpus/templates/slides/app/components/editor/SlideEditor.tsx +158 -31
- package/corpus/templates/slides/app/components/editor/SlideOverflowWarning.tsx +30 -14
- package/corpus/templates/slides/app/components/editor/SpeakerNotesPanel.tsx +2 -2
- package/corpus/templates/slides/app/components/editor/canvas-interactions/slides-canvas-adapter.ts +4 -1
- package/corpus/templates/slides/app/components/editor/rich-text-selection.ts +14 -0
- package/corpus/templates/slides/app/components/editor/slide-text-targets.ts +24 -0
- package/corpus/templates/slides/app/context/DeckContext.tsx +19 -31
- package/corpus/templates/slides/app/global.css +24 -0
- package/corpus/templates/slides/app/hooks/use-navigation-state.ts +20 -17
- package/corpus/templates/slides/app/i18n/en-US.ts +19 -10
- package/corpus/templates/slides/app/lib/deck-filter.ts +47 -0
- package/corpus/templates/slides/app/lib/export-google-slides-client.ts +15 -4
- package/corpus/templates/slides/app/lib/export-pptx-client.ts +637 -1
- package/corpus/templates/slides/app/lib/image-download.ts +84 -0
- package/corpus/templates/slides/app/lib/utils.ts +1 -1
- package/corpus/templates/slides/app/pages/DeckEditor.tsx +9 -0
- package/corpus/templates/slides/app/pages/Index.tsx +25 -9
- package/corpus/templates/slides/changelog/2026-08-13-clicking-a-slide-thumbnail-now-focuses-it-so-the-slide-shortc.md +6 -0
- package/corpus/templates/slides/changelog/2026-08-13-duplicating-or-restoring-a-slide-now-keeps-its-transition-ani.md +6 -0
- package/corpus/templates/slides/changelog/2026-08-13-opening-presentation-mode-from-the-agent-now-starts-on-the-re.md +6 -0
- package/corpus/templates/slides/changelog/2026-08-13-slide-transitions-can-be-set-from-a-visible-control-in-the-sl.md +6 -0
- package/corpus/templates/slides/netlify.toml +1 -0
- package/corpus/templates/slides/server/lib/builder-design-system-proxy.ts +14 -2
- package/dist/a2a/audience.d.ts +2 -0
- package/dist/a2a/audience.js +23 -0
- package/dist/a2a/client.d.ts +4 -0
- package/dist/a2a/client.js +32 -14
- package/dist/a2a/server.d.ts +9 -4
- package/dist/a2a/server.js +52 -25
- package/dist/a2a/types.d.ts +4 -4
- package/dist/agent/production-agent.js +1 -1
- package/dist/brand-kit/types.d.ts +10 -2
- package/dist/cli/code.js +1 -1
- package/dist/cli/index.js +30 -1
- package/dist/cli/native-dependencies.d.ts +24 -0
- package/dist/cli/native-dependencies.js +264 -0
- package/dist/cli/plan-local.js +1 -1
- package/dist/cli/skills-content/design-visual-edit-skill.d.ts +1 -1
- package/dist/cli/skills-content/design-visual-edit-skill.js +2 -2
- package/dist/cli/visualize-repo.js +1 -1
- package/dist/client/FeedbackButton.js +12 -12
- package/dist/client/agent-chat-adapter.js +3 -4
- package/dist/client/assistant-ui-recovery.d.ts +1 -1
- package/dist/client/assistant-ui-recovery.js +4 -0
- package/dist/client/chat/message-components.d.ts +11 -3
- package/dist/client/chat/message-components.js +31 -5
- package/dist/client/chat/tool-call-display.d.ts +2 -1
- package/dist/client/chat/tool-call-display.js +33 -15
- package/dist/client/db-admin/SqlEditor.js +1 -1
- package/dist/client/dev-overlay/DevOverlay.js +2 -2
- package/dist/client/extensions/portable-extension.js +4 -0
- package/dist/client/guided-questions.d.ts +8 -0
- package/dist/client/guided-questions.js +12 -3
- package/dist/client/sharing/ShareButton.js +16 -24
- package/dist/client/sse-event-processor.js +35 -15
- package/dist/client/tool-display.d.ts +9 -0
- package/dist/client/tool-display.js +39 -0
- package/dist/client/vite-dev-recovery-script.js +1 -1
- package/dist/collab/awareness.d.ts +2 -2
- package/dist/collab/routes.d.ts +1 -1
- package/dist/collab/struct-routes.d.ts +1 -1
- package/dist/extensions/html-shell.js +5 -0
- package/dist/notifications/routes.d.ts +1 -1
- package/dist/observability/routes.d.ts +3 -3
- package/dist/provider-api/actions/custom-provider-registration.d.ts +2 -2
- package/dist/server/agent-capabilities.js +0 -0
- package/dist/server/agent-chat/action-filters-a2a.d.ts +14 -13
- package/dist/server/agent-chat/action-filters-a2a.js +59 -23
- package/dist/server/agent-chat/prompt-resources.js +17 -16
- package/dist/server/agent-chat-plugin.d.ts +9 -0
- package/dist/server/agent-chat-plugin.js +29 -7
- package/dist/server/agent-engine-api-key-route.d.ts +1 -1
- package/dist/server/builder-design-systems.d.ts +33 -1
- package/dist/server/builder-design-systems.js +293 -11
- package/dist/server/design-token-utils.d.ts +11 -0
- package/dist/server/design-token-utils.js +68 -16
- package/dist/server/index.d.ts +1 -1
- package/dist/server/index.js +1 -1
- package/package.json +2 -2
|
@@ -13,6 +13,10 @@ export function assistantUiRecoverableRenderErrorKind(error) {
|
|
|
13
13
|
if (/^Tried to unmount a fiber that is already unmounted\b/.test(message)) {
|
|
14
14
|
return "assistant-ui-react-fiber-unmount";
|
|
15
15
|
}
|
|
16
|
+
// guard:allow-raw-color — #185 is a React diagnostic code, not a UI color.
|
|
17
|
+
if (/Maximum update depth exceeded|Minified React error #185/.test(message)) {
|
|
18
|
+
return "assistant-ui-react-update-depth";
|
|
19
|
+
}
|
|
16
20
|
return null;
|
|
17
21
|
}
|
|
18
22
|
export function isAssistantUiStaleIndexError(error) {
|
|
@@ -57,6 +57,10 @@ export declare function resolveAssistantRequestId(message: unknown, activeRun: {
|
|
|
57
57
|
runId: string;
|
|
58
58
|
} | null, threadId: string): string | undefined;
|
|
59
59
|
export declare function MessageBranchPicker(): React.JSX.Element;
|
|
60
|
+
export declare function ChatImageAttachmentPreview({ src, alt, }: {
|
|
61
|
+
src: string;
|
|
62
|
+
alt: string;
|
|
63
|
+
}): React.JSX.Element;
|
|
60
64
|
export declare function MessageActionsMenu({ showRevert, onRevert, threadId, }?: {
|
|
61
65
|
showRevert?: boolean;
|
|
62
66
|
onRevert?: () => void;
|
|
@@ -68,13 +72,14 @@ export declare function isMissingFinalResponseWarningText(text: string): boolean
|
|
|
68
72
|
export declare function latestUserMessageText(messages: readonly unknown[]): string;
|
|
69
73
|
export declare function userMessageTextBeforeAssistant(messages: readonly unknown[], assistantMessageId: string): string;
|
|
70
74
|
export declare function assistantMessageHasUnresolvedTool(content: unknown): boolean;
|
|
75
|
+
export declare function assistantMessageHasActiveTool(content: unknown): boolean;
|
|
71
76
|
export declare function assistantMessageHasCompletedCustomUi(content: unknown): boolean;
|
|
72
77
|
export declare function assistantMessageHasCustomUi(content: unknown): boolean;
|
|
73
78
|
export declare function computeActiveTailToolCallId(content: ContentPart[] | undefined, { chatRunning, isLast }: {
|
|
74
79
|
chatRunning: boolean;
|
|
75
80
|
isLast: boolean;
|
|
76
81
|
}): string | null;
|
|
77
|
-
export declare function shouldShowAssistantMessageFooter({ isLast, chatRunning, activeRunId, messageRunId, activeTurnId, messageTurnId, hasRenderableContent, statusIsTerminal, hasUnresolvedTool, }: {
|
|
82
|
+
export declare function shouldShowAssistantMessageFooter({ isLast, chatRunning, activeRunId, messageRunId, activeTurnId, messageTurnId, hasRenderableContent, statusIsTerminal, hasUnresolvedTool, hasActiveTool, }: {
|
|
78
83
|
isLast: boolean;
|
|
79
84
|
chatRunning: boolean;
|
|
80
85
|
activeRunId?: string | null;
|
|
@@ -84,6 +89,7 @@ export declare function shouldShowAssistantMessageFooter({ isLast, chatRunning,
|
|
|
84
89
|
hasRenderableContent: boolean;
|
|
85
90
|
statusIsTerminal: boolean;
|
|
86
91
|
hasUnresolvedTool?: boolean;
|
|
92
|
+
hasActiveTool?: boolean;
|
|
87
93
|
}): boolean;
|
|
88
94
|
/**
|
|
89
95
|
* Server-authoritative "a run for this thread is still active and running".
|
|
@@ -93,21 +99,23 @@ export declare function shouldShowAssistantMessageFooter({ isLast, chatRunning,
|
|
|
93
99
|
*/
|
|
94
100
|
export declare const ServerRunActiveContext: React.Context<boolean>;
|
|
95
101
|
export declare const UserStoppedRunContext: React.Context<(runId?: string) => boolean>;
|
|
96
|
-
export declare function shouldShowMissingFinalResponse({ isCurrentTurnRunning, serverRunActive, statusIsTerminal, hasAssistantText, hasUnresolvedTool, hasCompletedCustomUi, userStoppedRun, }: {
|
|
102
|
+
export declare function shouldShowMissingFinalResponse({ isCurrentTurnRunning, serverRunActive, statusIsTerminal, hasAssistantText, hasUnresolvedTool, hasCompletedCustomUi, hasActiveTool, userStoppedRun, }: {
|
|
97
103
|
isCurrentTurnRunning: boolean;
|
|
98
104
|
serverRunActive?: boolean;
|
|
99
105
|
statusIsTerminal: boolean;
|
|
100
106
|
hasAssistantText: boolean;
|
|
101
107
|
hasUnresolvedTool: boolean;
|
|
102
108
|
hasCompletedCustomUi?: boolean;
|
|
109
|
+
hasActiveTool?: boolean;
|
|
103
110
|
userStoppedRun?: boolean;
|
|
104
111
|
}): boolean;
|
|
105
112
|
export declare function useSettledFlag(active: boolean, delayMs: number): boolean;
|
|
106
|
-
export declare function shouldShowAssistantWorkSummary({ isLast, isComplete, hasCollapsibleWork, hasUnresolvedTool, chatRunning, }: {
|
|
113
|
+
export declare function shouldShowAssistantWorkSummary({ isLast, isComplete, hasCollapsibleWork, hasUnresolvedTool, hasActiveTool, chatRunning, }: {
|
|
107
114
|
isLast: boolean;
|
|
108
115
|
isComplete: boolean;
|
|
109
116
|
hasCollapsibleWork: boolean;
|
|
110
117
|
hasUnresolvedTool: boolean;
|
|
118
|
+
hasActiveTool?: boolean;
|
|
111
119
|
chatRunning: boolean;
|
|
112
120
|
}): boolean;
|
|
113
121
|
export declare function getAssistantWorkSummaryDurationMs(durationMs: number | null | undefined, groupStartIndex: number, firstWorkPartIndex: number): number | null | undefined;
|
|
@@ -11,11 +11,12 @@ import React, { useState, useEffect, useCallback, useRef } from "react";
|
|
|
11
11
|
import { getActiveRun } from "../active-run-state.js";
|
|
12
12
|
import { agentNativePath } from "../api-path.js";
|
|
13
13
|
import { writeClipboardText } from "../clipboard.js";
|
|
14
|
+
import { Dialog, DialogClose, DialogContent, DialogTitle, } from "../components/ui/dialog.js";
|
|
14
15
|
import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuLabel, DropdownMenuSeparator, DropdownMenuTrigger, } from "../components/ui/dropdown-menu.js";
|
|
15
16
|
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, } from "../components/ui/tooltip.js";
|
|
16
17
|
import { ThumbsFeedback } from "../observability/ThumbsFeedback.js";
|
|
17
18
|
import { McpConnectionSuggestion } from "../resources/McpConnectionSuggestion.js";
|
|
18
|
-
import { isCallAgentToolCallShadowed, shadowedCallAgentToolCallIds, } from "../tool-display.js";
|
|
19
|
+
import { isCallAgentToolCallShadowed, isToolCallActive, shadowedCallAgentToolCallIds, } from "../tool-display.js";
|
|
19
20
|
import { cn } from "../utils.js";
|
|
20
21
|
import { MarkdownText, renderMarkdownToClipboardHtml, SmoothMarkdownText, } from "./markdown-renderer.js";
|
|
21
22
|
import { getAssistantRunDurationMs } from "./repo-helpers.js";
|
|
@@ -292,11 +293,18 @@ function UserMessageAttachments() {
|
|
|
292
293
|
!!p.image);
|
|
293
294
|
const imageSrc = uploadUrl || imagePart?.image || null;
|
|
294
295
|
if (imageSrc) {
|
|
295
|
-
return (_jsx(
|
|
296
|
+
return (_jsx(ChatImageAttachmentPreview, { src: imageSrc, alt: att.name }, att.id));
|
|
296
297
|
}
|
|
297
298
|
return (_jsxs("div", { className: "flex items-center gap-1.5 rounded-lg border border-border/70 bg-muted/50 px-2 py-1.5 text-xs text-muted-foreground", title: att.name, children: [_jsx(IconFile, { className: "h-3.5 w-3.5 shrink-0" }), _jsx("span", { className: "truncate max-w-[120px]", children: att.name || "file" })] }, att.id));
|
|
298
299
|
}) }));
|
|
299
300
|
}
|
|
301
|
+
export function ChatImageAttachmentPreview({ src, alt, }) {
|
|
302
|
+
const [open, setOpen] = useState(false);
|
|
303
|
+
return (_jsxs(_Fragment, { children: [_jsx("button", { type: "button", "aria-label": `Preview ${alt}`, title: alt, onClick: () => setOpen(true), className: "h-16 w-16 cursor-zoom-in overflow-hidden rounded-lg border border-border/70 bg-muted/50 p-0 transition-[border-color,box-shadow] hover:border-foreground/40 hover:shadow-sm focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2", children: _jsx("img", { src: src, alt: alt, className: "h-full w-full object-cover" }) }), _jsx(Dialog, { open: open, onOpenChange: setOpen, children: _jsxs(DialogContent, { hideClose: true, "aria-describedby": undefined, className: "fixed inset-0 left-0 top-0 flex h-screen max-h-none w-screen max-w-none translate-x-0 translate-y-0 items-center justify-center gap-0 overflow-hidden rounded-none border-0 bg-foreground/90 p-0 text-background shadow-none backdrop-blur-sm dark:bg-background/95 dark:text-foreground", onOpenAutoFocus: (event) => event.preventDefault(), children: [_jsx(DialogTitle, { className: "sr-only", children: alt || "Image preview" }), _jsx("div", { className: "flex h-full w-full items-center justify-center overflow-auto p-6", onClick: (event) => {
|
|
304
|
+
if (event.target === event.currentTarget)
|
|
305
|
+
setOpen(false);
|
|
306
|
+
}, children: _jsx("img", { src: src, alt: alt, draggable: false, className: "max-h-[90vh] max-w-[92vw] rounded-lg object-contain shadow-2xl" }) }), _jsx(DialogClose, { asChild: true, children: _jsx("button", { type: "button", "aria-label": "Close image preview", className: "absolute end-4 top-4 inline-flex size-9 items-center justify-center rounded-full border border-background/25 bg-background/10 text-background transition-colors hover:bg-background/20 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring dark:border-foreground/25 dark:bg-foreground/10 dark:text-foreground dark:hover:bg-foreground/20", children: _jsx(IconX, { className: "size-4" }) }) })] }) })] }));
|
|
307
|
+
}
|
|
300
308
|
// ─── UserMessageEditComposer ──────────────────────────────────────────────────
|
|
301
309
|
function UserMessageEditComposer() {
|
|
302
310
|
return (_jsxs(ComposerPrimitive.Root, { className: "flex flex-col gap-2 rounded-lg border border-border bg-background px-3 py-2 shadow-sm", children: [_jsx(ComposerPrimitive.Input, { className: "w-full resize-none bg-transparent text-sm leading-relaxed text-foreground placeholder:text-muted-foreground focus:outline-none", rows: 1, submitMode: "enter" }), _jsxs("div", { className: "flex justify-end gap-2", children: [_jsx(ComposerPrimitive.Cancel, { asChild: true, children: _jsx("button", { type: "button", className: "cursor-pointer rounded-md px-2 py-1 text-xs font-medium text-muted-foreground hover:bg-accent hover:text-foreground", children: "Cancel" }) }), _jsx(ComposerPrimitive.Send, { asChild: true, children: _jsx("button", { type: "submit", className: "cursor-pointer rounded-md bg-foreground px-2 py-1 text-xs font-medium text-background hover:opacity-90 disabled:opacity-50", children: "Save" }) })] })] }));
|
|
@@ -545,6 +553,15 @@ export function assistantMessageHasUnresolvedTool(content) {
|
|
|
545
553
|
return record.type === "tool-call" && record.result === undefined;
|
|
546
554
|
});
|
|
547
555
|
}
|
|
556
|
+
export function assistantMessageHasActiveTool(content) {
|
|
557
|
+
if (!Array.isArray(content))
|
|
558
|
+
return false;
|
|
559
|
+
return content.some((part) => {
|
|
560
|
+
if (!part || typeof part !== "object")
|
|
561
|
+
return false;
|
|
562
|
+
return isToolCallActive(part);
|
|
563
|
+
});
|
|
564
|
+
}
|
|
548
565
|
export function assistantMessageHasCompletedCustomUi(content) {
|
|
549
566
|
if (!Array.isArray(content))
|
|
550
567
|
return false;
|
|
@@ -606,7 +623,7 @@ export function computeActiveTailToolCallId(content, { chatRunning, isLast }) {
|
|
|
606
623
|
? part.toolCallId
|
|
607
624
|
: latestToolCallId, null) ?? null);
|
|
608
625
|
}
|
|
609
|
-
export function shouldShowAssistantMessageFooter({ isLast, chatRunning, activeRunId, messageRunId, activeTurnId, messageTurnId, hasRenderableContent, statusIsTerminal, hasUnresolvedTool, }) {
|
|
626
|
+
export function shouldShowAssistantMessageFooter({ isLast, chatRunning, activeRunId, messageRunId, activeTurnId, messageTurnId, hasRenderableContent, statusIsTerminal, hasUnresolvedTool, hasActiveTool, }) {
|
|
610
627
|
if (!hasRenderableContent)
|
|
611
628
|
return false;
|
|
612
629
|
const ownsActiveTurn = activeTurnId != null &&
|
|
@@ -622,6 +639,8 @@ export function shouldShowAssistantMessageFooter({ isLast, chatRunning, activeRu
|
|
|
622
639
|
const ownsActiveRun = isLast || ownsActiveTurn || ownsLegacyRun;
|
|
623
640
|
if (chatRunning && ownsActiveRun)
|
|
624
641
|
return false;
|
|
642
|
+
if (hasActiveTool)
|
|
643
|
+
return false;
|
|
625
644
|
if (!isLast)
|
|
626
645
|
return true;
|
|
627
646
|
if (hasUnresolvedTool)
|
|
@@ -636,7 +655,7 @@ export function shouldShowAssistantMessageFooter({ isLast, chatRunning, activeRu
|
|
|
636
655
|
*/
|
|
637
656
|
export const ServerRunActiveContext = React.createContext(false);
|
|
638
657
|
export const UserStoppedRunContext = React.createContext(() => false);
|
|
639
|
-
export function shouldShowMissingFinalResponse({ isCurrentTurnRunning, serverRunActive, statusIsTerminal, hasAssistantText, hasUnresolvedTool, hasCompletedCustomUi, userStoppedRun, }) {
|
|
658
|
+
export function shouldShowMissingFinalResponse({ isCurrentTurnRunning, serverRunActive, statusIsTerminal, hasAssistantText, hasUnresolvedTool, hasCompletedCustomUi, hasActiveTool, userStoppedRun, }) {
|
|
640
659
|
if (userStoppedRun)
|
|
641
660
|
return false;
|
|
642
661
|
if (serverRunActive)
|
|
@@ -647,6 +666,7 @@ export function shouldShowMissingFinalResponse({ isCurrentTurnRunning, serverRun
|
|
|
647
666
|
statusIsTerminal &&
|
|
648
667
|
!hasAssistantText &&
|
|
649
668
|
!hasUnresolvedTool &&
|
|
669
|
+
!hasActiveTool &&
|
|
650
670
|
!hasCompletedCustomUi);
|
|
651
671
|
}
|
|
652
672
|
/**
|
|
@@ -668,9 +688,11 @@ export function useSettledFlag(active, delayMs) {
|
|
|
668
688
|
}, [active, delayMs]);
|
|
669
689
|
return active && (delayMs <= 0 || settled);
|
|
670
690
|
}
|
|
671
|
-
export function shouldShowAssistantWorkSummary({ isLast, isComplete, hasCollapsibleWork, hasUnresolvedTool, chatRunning, }) {
|
|
691
|
+
export function shouldShowAssistantWorkSummary({ isLast, isComplete, hasCollapsibleWork, hasUnresolvedTool, hasActiveTool, chatRunning, }) {
|
|
672
692
|
if (!hasCollapsibleWork)
|
|
673
693
|
return false;
|
|
694
|
+
if (hasActiveTool)
|
|
695
|
+
return false;
|
|
674
696
|
// An unresolved tool means "still working" only while the turn is actually
|
|
675
697
|
// running. On a stalled or interrupted turn it used to hide the summary
|
|
676
698
|
// forever, so the longest turns showed no "Worked for Xm Ys" at all.
|
|
@@ -798,6 +820,7 @@ export function AssistantMessage() {
|
|
|
798
820
|
const isUserStoppedRun = assistantMessageWasUserStopped(msg) || userStoppedRun(messageRunId);
|
|
799
821
|
const hasRenderableContent = assistantMessageHasRenderableContent(msg);
|
|
800
822
|
const hasUnresolvedTool = assistantMessageHasUnresolvedTool(msg.content);
|
|
823
|
+
const hasActiveTool = assistantMessageHasActiveTool(msg.content);
|
|
801
824
|
const missingWarningText = missingFinalResponseWarningText(msg.content);
|
|
802
825
|
const responseConnectionText = finalResponseTextFromContent(msg.content);
|
|
803
826
|
const statusIsTerminal = assistantMessageStatusIsTerminal(msg);
|
|
@@ -818,6 +841,7 @@ export function AssistantMessage() {
|
|
|
818
841
|
statusIsTerminal,
|
|
819
842
|
hasAssistantText: responseConnectionText.trim().length > 0,
|
|
820
843
|
hasUnresolvedTool,
|
|
844
|
+
hasActiveTool,
|
|
821
845
|
hasCompletedCustomUi,
|
|
822
846
|
userStoppedRun: isUserStoppedRun,
|
|
823
847
|
});
|
|
@@ -876,6 +900,7 @@ export function AssistantMessage() {
|
|
|
876
900
|
hasRenderableContent,
|
|
877
901
|
statusIsTerminal,
|
|
878
902
|
hasUnresolvedTool,
|
|
903
|
+
hasActiveTool,
|
|
879
904
|
});
|
|
880
905
|
const cpCtx = React.useContext(CheckpointContext);
|
|
881
906
|
useEffect(() => {
|
|
@@ -995,6 +1020,7 @@ export function AssistantMessage() {
|
|
|
995
1020
|
isComplete,
|
|
996
1021
|
hasCollapsibleWork,
|
|
997
1022
|
hasUnresolvedTool,
|
|
1023
|
+
hasActiveTool,
|
|
998
1024
|
chatRunning,
|
|
999
1025
|
});
|
|
1000
1026
|
if (!showSummary)
|
|
@@ -78,7 +78,7 @@ export declare function AnimatedCollapse({ open, children, }: {
|
|
|
78
78
|
open: boolean;
|
|
79
79
|
children: React.ReactNode;
|
|
80
80
|
}): React.JSX.Element | null;
|
|
81
|
-
export declare function ToolCallDisplay({ toolName, toolCallId, argsText, args, result, mcpApp, chatUI, isRunning, outcome, structuredMeta, approval, repeatCount, isLatestRunning, isActiveTail, }: {
|
|
81
|
+
export declare function ToolCallDisplay({ toolName, toolCallId, argsText, args, result, mcpApp, chatUI, isRunning, outcome, structuredMeta, activity, approval, repeatCount, isLatestRunning, isActiveTail, }: {
|
|
82
82
|
toolName: string;
|
|
83
83
|
toolCallId?: string;
|
|
84
84
|
argsText?: string;
|
|
@@ -90,6 +90,7 @@ export declare function ToolCallDisplay({ toolName, toolCallId, argsText, args,
|
|
|
90
90
|
/** "unknown": the stream ended mid-flight, so the side effect may have landed. */
|
|
91
91
|
outcome?: "unknown";
|
|
92
92
|
structuredMeta?: Record<string, unknown>;
|
|
93
|
+
activity?: boolean;
|
|
93
94
|
approval?: {
|
|
94
95
|
approvalKey: string;
|
|
95
96
|
dismissed?: boolean;
|
|
@@ -11,7 +11,7 @@ import { McpAppRenderer } from "../mcp-apps/McpAppRenderer.js";
|
|
|
11
11
|
import { findMcpIntegrationForToolName } from "../resources/mcp-integration-catalog.js";
|
|
12
12
|
import { McpIntegrationLogo } from "../resources/McpIntegrationLogo.js";
|
|
13
13
|
import { BashCell, EditCell, WriteCell, FilesChangedSummary, } from "../tool-cells/index.js";
|
|
14
|
-
import { humanizeToolName, isCallAgentToolCallShadowed, } from "../tool-display.js";
|
|
14
|
+
import { humanizeToolName, isCallAgentToolCallShadowed, isToolCallActive, } from "../tool-display.js";
|
|
15
15
|
import { cn } from "../utils.js";
|
|
16
16
|
import { ActionChatUiSurface } from "./action-chat-ui-surface.js";
|
|
17
17
|
import { SmoothMarkdownText, HighlightedCodeBlock, } from "./markdown-renderer.js";
|
|
@@ -273,23 +273,34 @@ function ApprovalAffordance({ toolName, toolCallId, approval, }) {
|
|
|
273
273
|
}, className: cn("inline-flex items-center gap-1 rounded-md border border-border px-2.5 py-1 text-xs font-medium transition-colors", "text-foreground hover:bg-muted"), children: [_jsx(IconX, { className: "h-3.5 w-3.5" }), "Deny"] })] }));
|
|
274
274
|
}
|
|
275
275
|
// ─── ToolCallDisplay ──────────────────────────────────────────────────────────
|
|
276
|
-
export function ToolCallDisplay({ toolName, toolCallId, argsText, args, result, mcpApp, chatUI, isRunning, outcome, structuredMeta, approval, repeatCount, isLatestRunning = isRunning, isActiveTail, }) {
|
|
276
|
+
export function ToolCallDisplay({ toolName, toolCallId, argsText, args, result, mcpApp, chatUI, isRunning, outcome, structuredMeta, activity, approval, repeatCount, isLatestRunning = isRunning, isActiveTail, }) {
|
|
277
|
+
const isDelegatedAgentCall = toolName === "call-agent" || toolName.startsWith("agent:");
|
|
278
|
+
const effectiveIsRunning = isRunning ||
|
|
279
|
+
(isDelegatedAgentCall &&
|
|
280
|
+
isToolCallActive({
|
|
281
|
+
type: "tool-call",
|
|
282
|
+
toolName,
|
|
283
|
+
result,
|
|
284
|
+
outcome,
|
|
285
|
+
activity,
|
|
286
|
+
structuredMeta,
|
|
287
|
+
}));
|
|
277
288
|
const showActiveTail = isActiveTail ?? isLatestRunning;
|
|
278
289
|
// Delegate to bespoke cells when structured metadata is present.
|
|
279
290
|
// These must be separate components so hook order in ToolCallDisplayGeneric
|
|
280
291
|
// is always stable (no conditional hook calls).
|
|
281
292
|
const toolKind = structuredMeta?.toolKind;
|
|
282
|
-
const wrapToolDisplay = (children) => (_jsx(ToolActivityPresentation, { toolName: toolName, isRunning:
|
|
293
|
+
const wrapToolDisplay = (children) => (_jsx(ToolActivityPresentation, { toolName: toolName, isRunning: effectiveIsRunning, toolCallId: toolCallId, suppressLongRunningHint: toolName === "call-agent" || toolName.startsWith("agent:"), children: children }));
|
|
283
294
|
if (toolKind === "bash") {
|
|
284
|
-
return wrapToolDisplay(_jsx(BashCell, { meta: structuredMeta, output: result, isRunning:
|
|
295
|
+
return wrapToolDisplay(_jsx(BashCell, { meta: structuredMeta, output: result, isRunning: effectiveIsRunning }));
|
|
285
296
|
}
|
|
286
297
|
if (toolKind === "edit") {
|
|
287
|
-
return wrapToolDisplay(_jsx(EditCell, { meta: structuredMeta, isRunning:
|
|
298
|
+
return wrapToolDisplay(_jsx(EditCell, { meta: structuredMeta, isRunning: effectiveIsRunning }));
|
|
288
299
|
}
|
|
289
300
|
if (toolKind === "write") {
|
|
290
|
-
return wrapToolDisplay(_jsx(WriteCell, { meta: structuredMeta, isRunning:
|
|
301
|
+
return wrapToolDisplay(_jsx(WriteCell, { meta: structuredMeta, isRunning: effectiveIsRunning }));
|
|
291
302
|
}
|
|
292
|
-
return wrapToolDisplay(_jsx(ToolCallDisplayGeneric, { toolName: toolName, toolCallId: toolCallId, argsText: argsText, args: args, result: result, mcpApp: mcpApp, chatUI: chatUI, isRunning:
|
|
303
|
+
return wrapToolDisplay(_jsx(ToolCallDisplayGeneric, { toolName: toolName, toolCallId: toolCallId, argsText: argsText, args: args, result: result, mcpApp: mcpApp, chatUI: chatUI, isRunning: effectiveIsRunning, outcome: outcome, isActiveTail: showActiveTail, structuredMeta: structuredMeta, approval: approval, repeatCount: repeatCount }));
|
|
293
304
|
}
|
|
294
305
|
function ToolCallDisplayGeneric({ toolName, toolCallId, argsText, args, result, mcpApp, chatUI, isRunning, outcome, isActiveTail, structuredMeta, approval, repeatCount, }) {
|
|
295
306
|
const suppressInlineOpenApp = React.useContext(SuppressInlineOpenAppContext);
|
|
@@ -460,17 +471,24 @@ function AgentActivityToolCallRow({ tool, isActiveTail, }) {
|
|
|
460
471
|
// ─── ToolCallFallback ──────────────────────────────────────────────────────────
|
|
461
472
|
export function ToolCallFallback({ toolName, toolCallId, args, argsText, result, ...rest }) {
|
|
462
473
|
const chatRunning = React.useContext(ChatRunningContext);
|
|
463
|
-
//
|
|
464
|
-
//
|
|
465
|
-
//
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
474
|
+
// `chatRunning` covers ordinary live activity. An unresolved tool or a
|
|
475
|
+
// delegated-agent row is also explicit work evidence, while a generic
|
|
476
|
+
// activity placeholder alone must stay frozen when history is rehydrated.
|
|
477
|
+
const isRunning = rest.outcome !== "unknown" &&
|
|
478
|
+
((result === undefined && chatRunning) ||
|
|
479
|
+
isToolCallActive({
|
|
480
|
+
type: "tool-call",
|
|
481
|
+
toolName,
|
|
482
|
+
result,
|
|
483
|
+
outcome: rest.outcome,
|
|
484
|
+
activity: rest.activity,
|
|
485
|
+
structuredMeta: rest.structuredMeta,
|
|
486
|
+
}));
|
|
469
487
|
return (_jsx(ToolCallDisplay, { toolName: toolName, toolCallId: toolCallId, args: args, argsText: argsText, result: typeof result === "string"
|
|
470
488
|
? result
|
|
471
489
|
: result !== undefined
|
|
472
490
|
? JSON.stringify(result)
|
|
473
|
-
: undefined, mcpApp: rest.mcpApp, chatUI: rest.chatUI, structuredMeta: rest.structuredMeta, isRunning: isRunning, outcome: rest.outcome, isActiveTail: rest.isActiveTail, isLatestRunning: rest.isLatestRunning, approval: rest.approval, repeatCount: rest.repeatCount }));
|
|
491
|
+
: undefined, mcpApp: rest.mcpApp, chatUI: rest.chatUI, structuredMeta: rest.structuredMeta, activity: rest.activity, isRunning: isRunning, outcome: rest.outcome, isActiveTail: rest.isActiveTail, isLatestRunning: rest.isLatestRunning, approval: rest.approval, repeatCount: rest.repeatCount }));
|
|
474
492
|
}
|
|
475
493
|
// ─── ReconnectStreamMessage ────────────────────────────────────────────────────
|
|
476
494
|
// Renders the agent's in-progress response during reconnection (outside
|
|
@@ -496,7 +514,7 @@ export function ReconnectStreamMessage({ content, allowActivitySpinner = true, }
|
|
|
496
514
|
if (part.type === "reasoning") {
|
|
497
515
|
return (_jsx(ReasoningCell, { text: part.text, isStreaming: chatRunning && i === streamingReasoningPartIndex, resetKey: `reconnect-reasoning-${i}`, defaultOpen: i === latestReasoningPartIndex, collapseWhenReplaced: i < latestReasoningPartIndex }, `reconnect-reasoning-${i}`));
|
|
498
516
|
}
|
|
499
|
-
return (_jsx(ToolCallDisplay, { toolName: part.toolName, toolCallId: part.toolCallId, argsText: part.argsText, args: part.args, result: part.result, mcpApp: part.mcpApp, chatUI: part.chatUI, structuredMeta: part.structuredMeta, outcome: part.outcome, isRunning: part.result === undefined &&
|
|
517
|
+
return (_jsx(ToolCallDisplay, { toolName: part.toolName, toolCallId: part.toolCallId, argsText: part.argsText, args: part.args, result: part.result, mcpApp: part.mcpApp, chatUI: part.chatUI, structuredMeta: part.structuredMeta, activity: part.activity, outcome: part.outcome, isRunning: part.result === undefined &&
|
|
500
518
|
(chatRunning || (allowActivitySpinner && part.activity === true)), isActiveTail: i === latestActiveToolIndex, approval: part.approval, repeatCount: part.repeatCount }, `reconnect-tool-${i}`));
|
|
501
519
|
};
|
|
502
520
|
const renderedParts = [];
|
|
@@ -343,7 +343,7 @@ export function SqlEditor({ dialect, tableNames, columnsByTable, requestConfig,
|
|
|
343
343
|
const hasResults = result !== null;
|
|
344
344
|
const canExport = hasResults && result.columns.length > 0;
|
|
345
345
|
// ─── Render ──────────────────────────────────────────────────────────────
|
|
346
|
-
return (_jsxs("div", { className: "flex h-full flex-col", children: [_jsxs("div", { className: "flex flex-wrap items-center gap-2 border-b border-border bg-background px-3 py-2", children: [_jsxs("button", { type: "button", onClick: runActiveStatement, disabled: running || !value.trim(), title: `Run selection / statement (${MOD}
|
|
346
|
+
return (_jsxs("div", { className: "flex h-full flex-col", children: [_jsxs("div", { className: "flex flex-wrap items-center gap-2 border-b border-border bg-background px-3 py-2", children: [_jsxs("button", { type: "button", onClick: runActiveStatement, disabled: running || !value.trim(), title: `Run selection / statement (${MOD} Enter)`, className: "inline-flex h-8 cursor-pointer items-center gap-1.5 rounded-md bg-primary px-3 text-xs font-semibold text-primary-foreground transition-colors hover:bg-primary/90 disabled:cursor-not-allowed disabled:opacity-50", children: [running ? (_jsx(IconLoader2, { size: 14, className: "animate-spin" })) : (_jsx(IconPlayerPlayFilled, { size: 14 })), "Run"] }), _jsxs("span", { className: "hidden text-[11px] text-muted-foreground sm:inline", children: [MOD, " Enter runs selection / statement \u00B7 ", MOD, " Shift Enter runs all"] }), _jsxs("div", { className: "ml-auto flex items-center gap-2", children: [_jsxs(Popover, { children: [_jsx(PopoverTrigger, { asChild: true, children: _jsxs(ToolbarButton, { title: "Query history", children: [_jsx(IconHistory, { size: 14 }), "History"] }) }), _jsxs(PopoverContent, { align: "end", className: "w-96 p-0", children: [_jsxs("div", { className: "flex items-center justify-between border-b border-border px-3 py-2", children: [_jsx("span", { className: "text-xs font-semibold text-foreground", children: "Recent queries" }), history.length > 0 && (_jsx("button", { type: "button", onClick: () => {
|
|
347
347
|
clearHistory();
|
|
348
348
|
setHistory([]);
|
|
349
349
|
}, className: "cursor-pointer text-[11px] text-muted-foreground hover:text-foreground", children: "Clear" }))] }), _jsx("div", { className: "max-h-80 overflow-auto py-1", children: history.length === 0 ? (_jsx("div", { className: "px-3 py-6 text-center text-xs text-muted-foreground", children: "No queries yet" })) : (history.map((h, i) => (_jsx("button", { type: "button", onClick: () => loadIntoEditor(h), className: "block w-full cursor-pointer truncate px-3 py-1.5 text-left font-mono text-[11px] text-foreground hover:bg-accent", title: h, children: h.replace(/\s+/g, " ").trim() }, i)))) })] })] }), _jsxs(Popover, { children: [_jsx(PopoverTrigger, { asChild: true, children: _jsxs(ToolbarButton, { title: "Saved snippets", children: [_jsx(IconBookmark, { size: 14 }), "Snippets"] }) }), _jsxs(PopoverContent, { align: "end", className: "w-96 p-0", children: [_jsxs("div", { className: "flex items-center justify-between border-b border-border px-3 py-2", children: [_jsx("span", { className: "text-xs font-semibold text-foreground", children: "Saved snippets" }), _jsxs("button", { type: "button", onClick: openSaveModal, disabled: !value.trim(), className: "inline-flex cursor-pointer items-center gap-1 text-[11px] text-muted-foreground hover:text-foreground disabled:cursor-not-allowed disabled:opacity-50", children: [_jsx(IconBookmarkPlus, { size: 13 }), "Save current"] })] }), _jsx("div", { className: "max-h-80 overflow-auto py-1", children: snippets.length === 0 ? (_jsx("div", { className: "px-3 py-6 text-center text-xs text-muted-foreground", children: "No saved snippets" })) : (snippets.map((s) => (_jsxs("div", { className: "group flex items-center gap-2 px-3 py-1.5 hover:bg-accent", children: [_jsxs("button", { type: "button", onClick: () => loadIntoEditor(s.sql), className: "min-w-0 flex-1 cursor-pointer text-left", title: s.sql, children: [_jsx("div", { className: "truncate text-xs font-medium text-foreground", children: s.name }), _jsx("div", { className: "truncate font-mono text-[10px] text-muted-foreground", children: s.sql.replace(/\s+/g, " ").trim() })] }), _jsx("button", { type: "button", onClick: () => removeSnippet(s.id), className: "cursor-pointer rounded p-1 text-muted-foreground opacity-0 transition-opacity hover:text-red-500 group-hover:opacity-100", title: "Delete snippet", children: _jsx(IconTrash, { size: 13 }) })] }, s.id)))) })] })] }), _jsxs(DropdownMenu, { children: [_jsx(DropdownMenuTrigger, { asChild: true, children: _jsxs(ToolbarButton, { title: "Export results", disabled: !canExport, children: [_jsx(IconDownload, { size: 14 }), "Export", _jsx(IconChevronDown, { size: 12, className: "opacity-60" })] }) }), _jsxs(DropdownMenuContent, { align: "end", children: [_jsx(DropdownMenuItem, { onClick: () => exportAs("csv"), children: "Download CSV" }), _jsx(DropdownMenuItem, { onClick: () => exportAs("json"), children: "Download JSON" })] })] })] })] }), _jsx("div", { className: "shrink-0 overflow-hidden border-b border-border", style: { height: editorHeight }, children: _jsx(CodeMirror, { ref: editorRef, value: value, onChange: setValue, height: `${editorHeight}px`, theme: isDark ? oneDark : undefined, extensions: extensions, placeholder: "Write SQL here\u2026", basicSetup: {
|
|
@@ -57,8 +57,8 @@ function DevOverlayPanel({ onClose }) {
|
|
|
57
57
|
const panels = useSyncExternalStore(subscribeDevPanels, listDevPanels, listDevPanels);
|
|
58
58
|
const shortcutHint = typeof navigator !== "undefined" &&
|
|
59
59
|
/Mac|iPhone|iPad/.test(navigator.userAgent)
|
|
60
|
-
? "Cmd
|
|
61
|
-
: "Ctrl
|
|
60
|
+
? "Cmd Ctrl A"
|
|
61
|
+
: "Ctrl Alt A";
|
|
62
62
|
return (_jsx(TooltipProvider, { delayDuration: 200, children: _jsxs("div", { style: styles.shell, role: "dialog", "aria-label": "Dev overlay", children: [_jsxs("div", { style: styles.header, children: [_jsxs("div", { children: [_jsx("div", { style: styles.headerTitle, children: "Dev Overlay" }), _jsxs("div", { style: styles.headerSub, children: [shortcutHint, " \u00B7 localStorage-backed"] })] }), _jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsx("button", { type: "button", style: styles.iconBtn, onClick: onClose, "aria-label": "Close", children: _jsx(IconX, { size: 16 }) }) }), _jsx(TooltipContent, { children: "Close (Esc)" })] })] }), _jsx("div", { style: styles.body, children: panels.length === 0 ? (_jsxs("div", { style: styles.empty, children: ["No panels registered. Call ", _jsx("code", { children: "registerDevPanel(...)" }), " from your template to add options here."] })) : (panels.map((panel) => _jsx(DevPanelCard, { panel: panel }, panel.id))) }), _jsx("div", { style: styles.footer, children: _jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsxs("button", { type: "button", style: { ...styles.footerBtn, ...styles.footerBtnDanger }, onClick: () => {
|
|
63
63
|
clearAllDevOverlayStorage();
|
|
64
64
|
}, children: [_jsx(IconTrash, { size: 13 }), "Clear all dev-overlay values"] }) }), _jsx(TooltipContent, { children: "Reset every dev-overlay value back to its default" })] }) })] }) }));
|
|
@@ -281,6 +281,10 @@ export function buildAgentNativeExtensionHtml({ extensionId, content, title, slo
|
|
|
281
281
|
</style>
|
|
282
282
|
<style>
|
|
283
283
|
*, *::before, *::after { box-sizing: border-box; border-color: hsl(var(--border, 214 32% 91%)); }
|
|
284
|
+
/* Alpine only honours x-cloak when a stylesheet hides it, and the exported
|
|
285
|
+
body snippet cannot supply one. Without this an x-cloak overlay paints
|
|
286
|
+
over the whole extension until Alpine boots — and forever if it never does. */
|
|
287
|
+
[x-cloak] { display: none !important; }
|
|
284
288
|
html, body { margin: 0; min-height: 100%; background: transparent; color: hsl(var(--foreground, 222 47% 11%)); }
|
|
285
289
|
body {
|
|
286
290
|
--agent-native-extension-padding: clamp(12px, 2vw, 20px);
|
|
@@ -40,6 +40,14 @@ export interface GuidedQuestionPayload {
|
|
|
40
40
|
submitLabel?: string;
|
|
41
41
|
submitMessage?: string;
|
|
42
42
|
skipMessage?: string;
|
|
43
|
+
/**
|
|
44
|
+
* Hidden context appended to whichever message this card sends. The card's
|
|
45
|
+
* answer opens a continuation turn that inherits nothing from the turn that
|
|
46
|
+
* posed it, so anything the follow-up work depends on — a linked design
|
|
47
|
+
* system, the user's original brief — has to travel with the payload or it
|
|
48
|
+
* is gone by the time the agent acts on the answer.
|
|
49
|
+
*/
|
|
50
|
+
submitContext?: string;
|
|
43
51
|
/**
|
|
44
52
|
* @internal Set by {@link askUserQuestion} for client-initiated questions.
|
|
45
53
|
* When present, `useGuidedQuestionFlow` resolves the matching in-memory
|
|
@@ -508,8 +508,13 @@ export function useGuidedQuestionFlow({ enabled = true, stateKey = "show-questio
|
|
|
508
508
|
}
|
|
509
509
|
const formattedAnswers = formatGuidedAnswersForAgent(answers);
|
|
510
510
|
const resolvedSubmitMessage = visiblePayload?.submitMessage ?? submitMessage;
|
|
511
|
-
const context =
|
|
512
|
-
|
|
511
|
+
const context = [
|
|
512
|
+
buildSubmitContext?.({ answers, formattedAnswers }) ??
|
|
513
|
+
defaultGuidedSubmitContext(formattedAnswers),
|
|
514
|
+
visiblePayload?.submitContext,
|
|
515
|
+
]
|
|
516
|
+
.filter(Boolean)
|
|
517
|
+
.join("\n\n");
|
|
513
518
|
sendToAgentChat({
|
|
514
519
|
message: resolvedSubmitMessage,
|
|
515
520
|
context,
|
|
@@ -526,7 +531,11 @@ export function useGuidedQuestionFlow({ enabled = true, stateKey = "show-questio
|
|
|
526
531
|
}
|
|
527
532
|
sendToAgentChat({
|
|
528
533
|
message: visiblePayload?.skipMessage ?? skipMessage,
|
|
529
|
-
|
|
534
|
+
// Skipping a variant set asks for another one — the replacement needs the
|
|
535
|
+
// same context the first set was built from.
|
|
536
|
+
context: [buildSkipContext?.(), visiblePayload?.submitContext]
|
|
537
|
+
.filter(Boolean)
|
|
538
|
+
.join("\n\n"),
|
|
530
539
|
submit: true,
|
|
531
540
|
});
|
|
532
541
|
clear();
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { Collapsible, CollapsibleContent, CollapsibleTrigger, } from "@agent-native/toolkit/ui";
|
|
3
2
|
import * as Select from "@radix-ui/react-select";
|
|
4
|
-
import { IconLock, IconWorld, IconTrash, IconCheck, IconChevronDown,
|
|
3
|
+
import { IconLock, IconWorld, IconTrash, IconCheck, IconChevronDown, IconLoader2, IconLink, IconSearch, IconSearchOff, IconShare3, IconUsersGroup, } from "@tabler/icons-react";
|
|
5
4
|
import { useEffect, useId, useRef, useState, } from "react";
|
|
6
5
|
import { writeClipboardText } from "../clipboard.js";
|
|
7
6
|
import { Popover, PopoverAnchor, PopoverContent, PopoverTrigger, } from "../components/ui/popover.js";
|
|
@@ -103,7 +102,7 @@ export function ShareButton(props) {
|
|
|
103
102
|
return (_jsxs(Popover, { open: controller.open, onOpenChange: controller.handleOpenChange, children: [_jsx(PopoverTrigger, { asChild: true, children: _jsxs("button", { type: "button", className: cn(iconOnly ? BUTTON_GHOST_ICON : BUTTON_OUTLINE_SM, props.triggerClassName), "aria-label": triggerLabel, title: triggerLabel, children: [showTriggerIcon && _jsx(TriggerIcon, { size: 16, strokeWidth: 1.75 }), !iconOnly && _jsx("span", { children: "Share" })] }) }), _jsx(PopoverContent, { align: "end", sideOffset: 6, "data-agent-native-share-overlay": "", className: cn("z-[2000] w-[min(460px,92vw)] rounded-lg p-4 shadow-lg", SHARE_POPOVER_SURFACE, props.popoverClassName), onOpenAutoFocus: (e) => e.preventDefault(), onInteractOutside: handleSharePopoverInteractOutside, children: _jsx(SharePanel, { ...props, controller: controller }) })] }));
|
|
104
103
|
}
|
|
105
104
|
function SharePanel(props) {
|
|
106
|
-
const {
|
|
105
|
+
const { controller } = props;
|
|
107
106
|
const { inviteEmail, setInviteEmail: onInviteEmailChange, activeShareTab, handleShareTabChange, data, policy, visibility, canManage, role, setRole, notifyPeople, setNotifyPeople, shareMessage, setShareMessage, messageOpen, setMessageOpen, shareError, setShareError, suggestionsOpen, setSuggestionsOpen, inFlight, memberSearch, memberSuggestions, knownMembers, shares, handleVisibility, handleHideInSearch, handleAdd, handleChangeRole, handleRemove, } = controller;
|
|
108
107
|
const hasInviteEmail = inviteEmail.trim().length > 0;
|
|
109
108
|
const isLoading = data === undefined;
|
|
@@ -116,28 +115,21 @@ function SharePanel(props) {
|
|
|
116
115
|
Boolean(props.shareUrlPlaceholder) ||
|
|
117
116
|
Boolean(props.secondaryShareUrl));
|
|
118
117
|
const shareUrlPlacement = props.shareUrlPlacement ?? "top";
|
|
119
|
-
const
|
|
120
|
-
useEffect(() => {
|
|
121
|
-
setAdvancedOpen(!showShareLinks);
|
|
122
|
-
}, [props.resourceId, showShareLinks]);
|
|
123
|
-
const extraTabs = props.shareTabs?.tabs ?? [];
|
|
118
|
+
const extraTabs = props.shareTabs?.tabs.filter((tab) => tab.value !== "context") ?? [];
|
|
124
119
|
const hasTabs = extraTabs.length > 0;
|
|
125
120
|
const shareTabLabel = props.shareTabs?.shareLabel ?? "Share link";
|
|
126
|
-
const
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
}, onSubmit: handleAdd, placeholder: policy.requireOrgMemberForUserShares
|
|
139
|
-
? "Add people from your organization"
|
|
140
|
-
: "Add people by email", suggestions: memberSuggestions, search: memberSearch }), _jsx(RoleSelect, { value: role, onChange: setRole, roleCopy: props.roleCopy, allowedRoles: props.allowedRoles }), _jsx("button", { type: "button", onClick: handleAdd, disabled: !hasInviteEmail, className: BUTTON_PRIMARY_SM, children: "Add" })] }), shareError ? (_jsx("div", { role: "alert", className: "rounded-md border border-destructive/40 bg-destructive/10 px-3 py-2 text-xs text-destructive", children: shareError })) : null, hasInviteEmail ? (_jsxs("div", { className: "flex flex-wrap items-center gap-x-3 gap-y-2 text-xs text-muted-foreground", children: [_jsxs("label", { className: "inline-flex items-center gap-2", children: [_jsx("input", { type: "checkbox", checked: notifyPeople, onChange: (e) => setNotifyPeople(e.target.checked), className: "h-4 w-4 rounded border-input accent-primary" }), "Notify people"] }), notifyPeople ? (_jsx("button", { type: "button", "aria-expanded": messageOpen, onClick: () => setMessageOpen(!messageOpen), className: "rounded-sm px-1 py-0.5 font-medium text-foreground underline decoration-border underline-offset-2 transition-colors hover:bg-accent hover:text-accent-foreground", children: messageOpen ? "Hide message" : "Add a message" })) : null] })) : null, hasInviteEmail && notifyPeople && messageOpen ? (_jsx("div", { className: "rounded-md border border-border/70 bg-muted/20 p-2.5", children: _jsx("textarea", { "aria-label": "Message", placeholder: "Add a short note (optional)", value: shareMessage, onChange: (event) => setShareMessage(event.target.value), maxLength: 500, rows: 3, className: "w-full resize-y rounded-md border border-input bg-card px-3 py-2 text-sm text-foreground placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 focus:ring-offset-background" }) })) : null] })) : null, _jsxs("div", { children: [_jsx("div", { className: "mb-2 text-sm font-semibold", children: peopleAccessLabel }), _jsxs("ul", { className: "flex flex-col gap-1 list-none p-0 m-0", children: [data?.ownerEmail ? (_jsxs("li", { className: "flex items-center gap-3 px-1 py-1.5 text-sm", children: [_jsx(Avatar, { label: displayName(data.ownerEmail, knownMembers) }), _jsx("span", { className: "flex-1 min-w-0 truncate", children: displayName(data.ownerEmail, knownMembers) }), _jsx("span", { className: "text-xs text-muted-foreground", children: "Owner" })] })) : null, shares.map((s) => (_jsxs("li", { className: cn("flex items-center gap-3 px-1 py-1.5 text-sm", inFlight.has(keyOf(s)) && "opacity-60"), children: [_jsx(Avatar, { label: principalLabel(s, knownMembers), org: s.principalType === "org" }), _jsx("span", { className: "flex-1 min-w-0 truncate", children: principalLabel(s, knownMembers) }), canManage ? (_jsx(RoleSelect, { value: s.role, onChange: (r) => handleChangeRole(s, r), disabled: inFlight.has(keyOf(s)), plain: true, roleCopy: props.roleCopy, allowedRoles: props.allowedRoles })) : (_jsx("span", { className: "text-xs text-muted-foreground", children: roleMeta(s.role, props.roleCopy).label })), canManage ? (_jsx("button", { type: "button", "aria-label": "Remove", onClick: () => handleRemove(s), disabled: inFlight.has(keyOf(s)), className: BUTTON_GHOST_ICON, children: _jsx(IconTrash, { size: 14 }) })) : null] }, keyOf(s)))), !shares.length && !data?.ownerEmail ? (_jsx("li", { className: "px-1 py-1.5 text-sm text-muted-foreground", children: "No one has access yet." })) : null] })] })] }) })] }), _jsx("div", { className: "mb-2 text-sm font-semibold", children: generalAccessLabel }), _jsxs("div", { className: "mb-4 flex items-center gap-3", children: [_jsx("span", { "aria-hidden": true, className: "inline-flex h-9 w-9 shrink-0 items-center justify-center rounded-full bg-muted text-muted-foreground", children: _jsx(meta.Icon, { size: 16, strokeWidth: 1.75 }) }), _jsxs("div", { className: "min-w-0 flex-1", children: [_jsx(VisibilitySelect, { value: visibility, onChange: handleVisibility, disabled: !canManage, visibilityCopy: props.visibilityCopy, allowPublic: policy.allowPublic }), _jsxs("div", { className: "mt-0.5 flex flex-wrap items-center gap-x-2 gap-y-1 text-xs text-muted-foreground", children: [_jsx("span", { className: "sr-only", children: meta.description }), visibility === "org" && props.hideInSearchControl ? (_jsx(AdvancedAccessPopover, { control: props.hideInSearchControl, canManage: canManage, onToggle: handleHideInSearch })) : null] })] })] }), shareError && !canManage ? (_jsx("div", { role: "alert", className: "mb-4 rounded-md border border-destructive/40 bg-destructive/10 px-3 py-2 text-xs text-destructive", children: shareError })) : null, props.accessNote ? (_jsx("div", { className: "mb-4 rounded-md border border-border bg-muted/35 p-3 text-xs text-muted-foreground", children: props.accessNote })) : null, showShareLinks && shareUrlPlacement === "bottom" ? shareLinks : null, props.shareFooterContent] }));
|
|
121
|
+
const sharePanel = isLoading ? (_jsxs("div", { children: [showShareLinks ? (_jsx("div", { className: "mb-4 h-9 rounded-md bg-muted animate-pulse" })) : null, _jsx("div", { className: "mb-2 text-sm font-semibold", children: generalAccessLabel }), _jsx("div", { className: "mb-4 h-9 rounded-md bg-muted animate-pulse" }), _jsx("div", { className: "mb-2 text-sm font-semibold", children: peopleAccessLabel }), _jsx("div", { className: "mb-4 h-7 rounded-md bg-muted animate-pulse" })] })) : (_jsxs("div", { children: [showShareLinks && shareUrlPlacement === "top" ? shareLinks : null, _jsxs("div", { className: "mb-4", children: [_jsx("div", { className: "mb-2 text-sm font-semibold", children: generalAccessLabel }), _jsxs("div", { className: "flex items-center gap-3", children: [_jsx("span", { "aria-hidden": true, className: "inline-flex h-9 w-9 shrink-0 items-center justify-center rounded-full bg-muted text-muted-foreground", children: _jsx(meta.Icon, { size: 16, strokeWidth: 1.75 }) }), _jsxs("div", { className: "min-w-0 flex-1", children: [_jsx(VisibilitySelect, { value: visibility, onChange: handleVisibility, disabled: !canManage, visibilityCopy: props.visibilityCopy, allowPublic: policy.allowPublic }), _jsxs("div", { className: "mt-0.5 flex flex-wrap items-center gap-x-2 gap-y-1 text-xs text-muted-foreground", children: [_jsx("span", { className: "sr-only", children: meta.description }), visibility === "org" && props.hideInSearchControl ? (_jsx(AdvancedAccessPopover, { control: props.hideInSearchControl, canManage: canManage, onToggle: handleHideInSearch })) : null] })] })] })] }), _jsxs("div", { className: "mb-4 space-y-4", children: [_jsx("div", { className: "text-sm font-semibold", children: peopleAccessLabel }), canManage ? (_jsxs("div", { className: "space-y-2", children: [_jsxs("div", { className: "flex items-stretch gap-2", children: [_jsx(MemberAutocomplete, { value: inviteEmail, open: suggestionsOpen, onOpenChange: setSuggestionsOpen, onValueChange: (next) => {
|
|
122
|
+
onInviteEmailChange(next);
|
|
123
|
+
if (shareError)
|
|
124
|
+
setShareError(null);
|
|
125
|
+
}, onSelectMember: (member) => {
|
|
126
|
+
onInviteEmailChange(member.email);
|
|
127
|
+
setSuggestionsOpen(false);
|
|
128
|
+
if (shareError)
|
|
129
|
+
setShareError(null);
|
|
130
|
+
}, onSubmit: handleAdd, placeholder: policy.requireOrgMemberForUserShares
|
|
131
|
+
? "Add people from your organization"
|
|
132
|
+
: "Add people by email", suggestions: memberSuggestions, search: memberSearch }), _jsx(RoleSelect, { value: role, onChange: setRole, roleCopy: props.roleCopy, allowedRoles: props.allowedRoles }), _jsx("button", { type: "button", onClick: handleAdd, disabled: !hasInviteEmail, className: BUTTON_PRIMARY_SM, children: "Add" })] }), shareError ? (_jsx("div", { role: "alert", className: "rounded-md border border-destructive/40 bg-destructive/10 px-3 py-2 text-xs text-destructive", children: shareError })) : null, hasInviteEmail ? (_jsxs("div", { className: "flex flex-wrap items-center gap-x-3 gap-y-2 text-xs text-muted-foreground", children: [_jsxs("label", { className: "inline-flex items-center gap-2", children: [_jsx("input", { type: "checkbox", checked: notifyPeople, onChange: (e) => setNotifyPeople(e.target.checked), className: "h-4 w-4 rounded border-input accent-primary" }), "Notify people"] }), notifyPeople ? (_jsx("button", { type: "button", "aria-expanded": messageOpen, onClick: () => setMessageOpen(!messageOpen), className: "rounded-sm px-1 py-0.5 font-medium text-foreground underline decoration-border underline-offset-2 transition-colors hover:bg-accent hover:text-accent-foreground", children: messageOpen ? "Hide message" : "Add a message" })) : null] })) : null, hasInviteEmail && notifyPeople && messageOpen ? (_jsx("div", { className: "rounded-md border border-border/70 bg-muted/20 p-2.5", children: _jsx("textarea", { "aria-label": "Message", placeholder: "Add a short note (optional)", value: shareMessage, onChange: (event) => setShareMessage(event.target.value), maxLength: 500, rows: 3, className: "w-full resize-y rounded-md border border-input bg-card px-3 py-2 text-sm text-foreground placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 focus:ring-offset-background" }) })) : null] })) : null, _jsxs("ul", { className: "flex list-none flex-col gap-1 p-0 m-0", children: [data?.ownerEmail ? (_jsxs("li", { className: "flex items-center gap-3 px-1 py-1.5 text-sm", children: [_jsx(Avatar, { label: displayName(data.ownerEmail, knownMembers) }), _jsx("span", { className: "flex-1 min-w-0 truncate", children: displayName(data.ownerEmail, knownMembers) }), _jsx("span", { className: "text-xs text-muted-foreground", children: "Owner" })] })) : null, shares.map((s) => (_jsxs("li", { className: cn("flex items-center gap-3 px-1 py-1.5 text-sm", inFlight.has(keyOf(s)) && "opacity-60"), children: [_jsx(Avatar, { label: principalLabel(s, knownMembers), org: s.principalType === "org" }), _jsx("span", { className: "flex-1 min-w-0 truncate", children: principalLabel(s, knownMembers) }), canManage ? (_jsx(RoleSelect, { value: s.role, onChange: (r) => handleChangeRole(s, r), disabled: inFlight.has(keyOf(s)), plain: true, roleCopy: props.roleCopy, allowedRoles: props.allowedRoles })) : (_jsx("span", { className: "text-xs text-muted-foreground", children: roleMeta(s.role, props.roleCopy).label })), canManage ? (_jsx("button", { type: "button", "aria-label": "Remove", onClick: () => handleRemove(s), disabled: inFlight.has(keyOf(s)), className: BUTTON_GHOST_ICON, children: _jsx(IconTrash, { size: 14 }) })) : null] }, keyOf(s)))), !shares.length && !data?.ownerEmail ? (_jsx("li", { className: "px-1 py-1.5 text-sm text-muted-foreground", children: "No one has access yet." })) : null] })] }), shareError && !canManage ? (_jsx("div", { role: "alert", className: "mb-4 rounded-md border border-destructive/40 bg-destructive/10 px-3 py-2 text-xs text-destructive", children: shareError })) : null, props.accessNote ? (_jsx("div", { className: "mb-4 rounded-md border border-border bg-muted/35 p-3 text-xs text-muted-foreground", children: props.accessNote })) : null, showShareLinks && shareUrlPlacement === "bottom" ? shareLinks : null, props.shareFooterContent] }));
|
|
141
133
|
if (!hasTabs)
|
|
142
134
|
return sharePanel;
|
|
143
135
|
const tabs = [
|
|
@@ -280,7 +272,7 @@ function CopyLinkField({ value, label = "Share link", description, }) {
|
|
|
280
272
|
setCopied(false);
|
|
281
273
|
}
|
|
282
274
|
};
|
|
283
|
-
return (_jsxs("div", { className: "mb-4", children: [
|
|
275
|
+
return (_jsxs("div", { className: "mb-4 flex items-center justify-between gap-4", children: [_jsxs("div", { className: "min-w-0", children: [_jsx("div", { className: "text-sm font-semibold", children: label }), description ? (_jsx("div", { className: "mt-1 text-xs text-muted-foreground", children: description })) : null] }), _jsxs("button", { type: "button", onClick: handleCopy, "aria-label": copied ? "Link copied" : "Copy", className: "inline-flex h-9 shrink-0 items-center gap-2 whitespace-nowrap rounded-md border border-input bg-card px-3 text-sm font-medium text-foreground hover:bg-accent", children: [copied ? _jsx(IconCheck, { size: 15 }) : _jsx(IconLink, { size: 15 }), copied ? "Copied" : "Copy"] })] }));
|
|
284
276
|
}
|
|
285
277
|
// ---------------------------------------------------------------------------
|
|
286
278
|
// Radix Select wrappers styled like shadcn Select (no native <select> anywhere)
|