@agent-native/core 0.153.10 → 0.154.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/corpus/README.md +1 -1
- package/corpus/templates/analytics/AGENTS.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/app/i18n-data.ts +10 -10
- package/corpus/templates/content/scripts/check-native-deps.mjs +181 -15
- 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/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/EditorSidebar.tsx +58 -33
- package/corpus/templates/slides/app/components/editor/EditorToolbar.tsx +28 -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/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/global.css +24 -0
- package/corpus/templates/slides/app/hooks/use-navigation-state.ts +5 -1
- 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/Index.tsx +25 -9
- package/corpus/templates/slides/netlify.toml +1 -0
- package/corpus/templates/slides/server/lib/builder-design-system-proxy.ts +14 -2
- 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/resources/handlers.d.ts +1 -1
- package/dist/secrets/routes.d.ts +3 -3
- 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/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 +3 -3
|
@@ -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)
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { LLM_MISSING_CREDENTIALS_ERROR_CODE, LLM_MISSING_CREDENTIALS_MESSAGE, } from "../agent/engine/credential-errors.js";
|
|
2
2
|
import { emitChatFirstOpenApp } from "./chat-first.js";
|
|
3
3
|
import { formatChatErrorText, normalizeChatError } from "./error-format.js";
|
|
4
|
-
import { humanizeToolLabelText, humanizeToolName, runningToolLabel, } from "./tool-display.js";
|
|
4
|
+
import { humanizeToolLabelText, humanizeToolName, isToolCallActive, runningToolLabel, } from "./tool-display.js";
|
|
5
5
|
/**
|
|
6
6
|
* Kept verbatim in sync with `INTERRUPTED_TOOL_RESULT_MARKER`
|
|
7
7
|
* (agent/production-agent.ts): the server matches this substring in replayed
|
|
@@ -13,16 +13,21 @@ const INTERRUPTED_ACTIVITY_RESULT = "Stopped before this action started.";
|
|
|
13
13
|
/**
|
|
14
14
|
* Maximum number of assistant-ui repository updates we deliver in one browser
|
|
15
15
|
* event-loop turn. Durable-run replay can put hundreds of SSE frames into the
|
|
16
|
-
* stream queue before the client attaches;
|
|
17
|
-
* assistant-ui
|
|
18
|
-
*
|
|
16
|
+
* stream queue before the client attaches; allowing even a small burst through
|
|
17
|
+
* assistant-ui can synchronously nest React external-store notifications until
|
|
18
|
+
* React throws "Maximum update depth exceeded."
|
|
19
19
|
*
|
|
20
|
-
* A
|
|
20
|
+
* A task scheduled on the first result resets the count when the stream is
|
|
21
21
|
* naturally idle between network chunks. We only await it when results are
|
|
22
22
|
* arriving densely enough to hit this bound, so normal live token streaming
|
|
23
23
|
* keeps its existing latency while replay bursts yield cooperatively.
|
|
24
24
|
*/
|
|
25
|
-
const SSE_RENDER_UPDATES_PER_EVENT_LOOP_TURN =
|
|
25
|
+
const SSE_RENDER_UPDATES_PER_EVENT_LOOP_TURN = 1;
|
|
26
|
+
function waitForNextEventLoopTurn() {
|
|
27
|
+
return new Promise((resolve) => {
|
|
28
|
+
setTimeout(resolve, 0);
|
|
29
|
+
});
|
|
30
|
+
}
|
|
26
31
|
export function settleInterruptedToolCalls(content, result = INTERRUPTED_TOOL_RESULT, options) {
|
|
27
32
|
let changed = false;
|
|
28
33
|
for (const part of content) {
|
|
@@ -825,6 +830,8 @@ function hasCompletedCustomUi(content) {
|
|
|
825
830
|
return hasCompletedTool && lastCompletedToolIsCustomUi;
|
|
826
831
|
}
|
|
827
832
|
export function appendMissingFinalResponseWarning(content, completedToolNames) {
|
|
833
|
+
if (content.some((part) => isToolCallActive(part)))
|
|
834
|
+
return null;
|
|
828
835
|
const lastTextIndex = lastAssistantTextIndex(content);
|
|
829
836
|
const successfulToolNames = [
|
|
830
837
|
...new Set(completedToolNames ?? completedToolNamesAfterLastAssistantText(content)),
|
|
@@ -1245,6 +1252,7 @@ export function processEvent(ev, content, toolCallCounter, tabId, state) {
|
|
|
1245
1252
|
: "Done";
|
|
1246
1253
|
part.structuredMeta = {
|
|
1247
1254
|
...part.structuredMeta,
|
|
1255
|
+
...(ev.status === "pending" ? { agentPending: true } : {}),
|
|
1248
1256
|
...(ev.durationMs != null
|
|
1249
1257
|
? { agentDurationMs: ev.durationMs }
|
|
1250
1258
|
: {}),
|
|
@@ -1618,15 +1626,19 @@ export async function* readSSEStream(body, content, toolCallCounter, tabId, onSe
|
|
|
1618
1626
|
const currentNoProgressTimeoutMs = () => inFlightWork > 0
|
|
1619
1627
|
? Math.max(noProgressTimeoutMs, SSE_IN_FLIGHT_WORK_TIMEOUT_MS)
|
|
1620
1628
|
: noProgressTimeoutMs;
|
|
1621
|
-
const paceRenderUpdate = async () => {
|
|
1629
|
+
const paceRenderUpdate = async (hasBufferedEvent) => {
|
|
1630
|
+
// A single event in a network chunk already has a natural read boundary.
|
|
1631
|
+
// Avoid inserting a task into quiet streams so watchdogs and fake-clock
|
|
1632
|
+
// consumers can continue to observe their own timers normally.
|
|
1633
|
+
if (!hasBufferedEvent) {
|
|
1634
|
+
renderUpdatesThisTurn = 0;
|
|
1635
|
+
return;
|
|
1636
|
+
}
|
|
1622
1637
|
renderUpdatesThisTurn += 1;
|
|
1623
1638
|
if (!nextEventLoopTurn) {
|
|
1624
|
-
nextEventLoopTurn =
|
|
1625
|
-
|
|
1626
|
-
|
|
1627
|
-
nextEventLoopTurn = null;
|
|
1628
|
-
resolve();
|
|
1629
|
-
}, 0);
|
|
1639
|
+
nextEventLoopTurn = waitForNextEventLoopTurn().then(() => {
|
|
1640
|
+
renderUpdatesThisTurn = 0;
|
|
1641
|
+
nextEventLoopTurn = null;
|
|
1630
1642
|
});
|
|
1631
1643
|
}
|
|
1632
1644
|
if (renderUpdatesThisTurn >= SSE_RENDER_UPDATES_PER_EVENT_LOOP_TURN) {
|
|
@@ -1686,12 +1698,19 @@ export async function* readSSEStream(body, content, toolCallCounter, tabId, onSe
|
|
|
1686
1698
|
const lines = buf.split("\n");
|
|
1687
1699
|
buf = lines.pop() ?? "";
|
|
1688
1700
|
let sawProgressEvent = false;
|
|
1689
|
-
|
|
1701
|
+
let bufferedDataEvents = lines.reduce((count, pendingLine) => count +
|
|
1702
|
+
(pendingLine.startsWith("data: ") &&
|
|
1703
|
+
pendingLine.slice(6).trim().length > 0
|
|
1704
|
+
? 1
|
|
1705
|
+
: 0), 0);
|
|
1706
|
+
for (let lineIndex = 0; lineIndex < lines.length; lineIndex += 1) {
|
|
1707
|
+
const line = lines[lineIndex];
|
|
1690
1708
|
if (!line.startsWith("data: "))
|
|
1691
1709
|
continue;
|
|
1692
1710
|
const raw = line.slice(6).trim();
|
|
1693
1711
|
if (!raw)
|
|
1694
1712
|
continue;
|
|
1713
|
+
bufferedDataEvents -= 1;
|
|
1695
1714
|
let ev;
|
|
1696
1715
|
try {
|
|
1697
1716
|
ev = JSON.parse(raw);
|
|
@@ -1751,7 +1770,8 @@ export async function* readSSEStream(body, content, toolCallCounter, tabId, onSe
|
|
|
1751
1770
|
}
|
|
1752
1771
|
: result;
|
|
1753
1772
|
if (terminalResult) {
|
|
1754
|
-
|
|
1773
|
+
const hasBufferedEvent = bufferedDataEvents > 0;
|
|
1774
|
+
await paceRenderUpdate(hasBufferedEvent);
|
|
1755
1775
|
yield withStreamMetadata(terminalResult);
|
|
1756
1776
|
}
|
|
1757
1777
|
if (hasStalledPreparingAction(preparingActionState, Date.now(), preparationStallTimeoutMs)) {
|
|
@@ -7,7 +7,16 @@ type ToolDisplayPart = {
|
|
|
7
7
|
toolName?: string;
|
|
8
8
|
argsText?: string;
|
|
9
9
|
args?: Record<string, unknown>;
|
|
10
|
+
result?: unknown;
|
|
11
|
+
outcome?: "unknown";
|
|
12
|
+
activity?: boolean;
|
|
13
|
+
structuredMeta?: Record<string, unknown>;
|
|
10
14
|
};
|
|
15
|
+
export declare function isDelegatedAgentToolCall(part: ToolDisplayPart): boolean;
|
|
16
|
+
/** True when a tool has not reported a result and the stream did not mark it unknown. */
|
|
17
|
+
export declare function isToolCallInFlight(part: ToolDisplayPart): boolean;
|
|
18
|
+
/** True when the UI must not present this tool as finished. */
|
|
19
|
+
export declare function isToolCallActive(part: ToolDisplayPart): boolean;
|
|
11
20
|
/**
|
|
12
21
|
* `call-agent` emits both its ordinary tool row and a richer `agent:<name>`
|
|
13
22
|
* progress row. Keep the ordinary part in message state for tool completion
|
|
@@ -33,6 +33,45 @@ export function humanizeToolLabelText(label, toolName) {
|
|
|
33
33
|
return text;
|
|
34
34
|
return text.split(tool).join(humanizeToolName(tool));
|
|
35
35
|
}
|
|
36
|
+
const ACTIVE_AGENT_ACTIVITY_PHASES = new Set([
|
|
37
|
+
"reasoning",
|
|
38
|
+
"tool",
|
|
39
|
+
"responding",
|
|
40
|
+
]);
|
|
41
|
+
export function isDelegatedAgentToolCall(part) {
|
|
42
|
+
return (part.type === "tool-call" && part.toolName?.startsWith("agent:") === true);
|
|
43
|
+
}
|
|
44
|
+
function hasActiveDelegatedAgentActivity(part) {
|
|
45
|
+
const snapshot = part.structuredMeta?.agentActivity;
|
|
46
|
+
if (!snapshot || typeof snapshot !== "object")
|
|
47
|
+
return false;
|
|
48
|
+
const record = snapshot;
|
|
49
|
+
if (typeof record.activePhase === "string" &&
|
|
50
|
+
ACTIVE_AGENT_ACTIVITY_PHASES.has(record.activePhase)) {
|
|
51
|
+
return true;
|
|
52
|
+
}
|
|
53
|
+
return (Array.isArray(record.toolCalls) &&
|
|
54
|
+
record.toolCalls.some((tool) => tool != null &&
|
|
55
|
+
typeof tool === "object" &&
|
|
56
|
+
tool.status === "running"));
|
|
57
|
+
}
|
|
58
|
+
/** True when a tool has not reported a result and the stream did not mark it unknown. */
|
|
59
|
+
export function isToolCallInFlight(part) {
|
|
60
|
+
if (part.type !== "tool-call")
|
|
61
|
+
return false;
|
|
62
|
+
if (part.result !== undefined || part.outcome === "unknown")
|
|
63
|
+
return false;
|
|
64
|
+
return part.activity !== true || isDelegatedAgentToolCall(part);
|
|
65
|
+
}
|
|
66
|
+
/** True when the UI must not present this tool as finished. */
|
|
67
|
+
export function isToolCallActive(part) {
|
|
68
|
+
if (isToolCallInFlight(part))
|
|
69
|
+
return true;
|
|
70
|
+
return (isDelegatedAgentToolCall(part) &&
|
|
71
|
+
part.outcome !== "unknown" &&
|
|
72
|
+
(part.structuredMeta?.agentPending === true ||
|
|
73
|
+
hasActiveDelegatedAgentActivity(part)));
|
|
74
|
+
}
|
|
36
75
|
function normalizedAgentName(value) {
|
|
37
76
|
if (typeof value !== "string")
|
|
38
77
|
return null;
|
|
@@ -87,7 +87,7 @@ export function getViteDevRecoveryScript() {
|
|
|
87
87
|
console.warn("[agent-native] Dev server keeps re-bundling. Manual refresh needed.", reason);
|
|
88
88
|
showOverlay(
|
|
89
89
|
"Dev server out of sync",
|
|
90
|
-
"Auto-reload gave up after " + MAX_RELOADS + " tries. Refresh the page (\\u2318R / Ctrl
|
|
90
|
+
"Auto-reload gave up after " + MAX_RELOADS + " tries. Refresh the page (\\u2318R / Ctrl R)."
|
|
91
91
|
);
|
|
92
92
|
return;
|
|
93
93
|
}
|
|
@@ -62,11 +62,11 @@ export declare const postAwareness: import("h3").EventHandlerWithFetch<import("h
|
|
|
62
62
|
error: string;
|
|
63
63
|
states?: undefined;
|
|
64
64
|
} | {
|
|
65
|
-
error?: undefined;
|
|
66
65
|
states: {
|
|
67
66
|
clientId: number;
|
|
68
67
|
state: string;
|
|
69
68
|
}[];
|
|
69
|
+
error?: undefined;
|
|
70
70
|
}>>;
|
|
71
71
|
/**
|
|
72
72
|
* GET /_agent-native/collab/:docId/users
|
|
@@ -77,9 +77,9 @@ export declare const getActiveUsers: import("h3").EventHandlerWithFetch<import("
|
|
|
77
77
|
error: string;
|
|
78
78
|
users?: undefined;
|
|
79
79
|
} | {
|
|
80
|
-
error?: undefined;
|
|
81
80
|
users: {
|
|
82
81
|
clientId: number;
|
|
83
82
|
lastSeen: number;
|
|
84
83
|
}[];
|
|
84
|
+
error?: undefined;
|
|
85
85
|
}>>;
|
package/dist/collab/routes.d.ts
CHANGED
|
@@ -26,8 +26,8 @@ export declare const getCollabState: import("h3").EventHandlerWithFetch<import("
|
|
|
26
26
|
* Body: { update: string (base64), requestSource?: string }
|
|
27
27
|
*/
|
|
28
28
|
export declare const postCollabUpdate: import("h3").EventHandlerWithFetch<import("h3").EventHandlerRequest, Promise<{
|
|
29
|
-
ok?: undefined;
|
|
30
29
|
error: string;
|
|
30
|
+
ok?: undefined;
|
|
31
31
|
} | {
|
|
32
32
|
error?: undefined;
|
|
33
33
|
ok: boolean;
|
|
@@ -13,8 +13,8 @@
|
|
|
13
13
|
* Body: { json: any, fieldName?: string, type?: "map"|"array", requestSource?: string }
|
|
14
14
|
*/
|
|
15
15
|
export declare const postCollabJson: import("h3").EventHandlerWithFetch<import("h3").EventHandlerRequest, Promise<{
|
|
16
|
-
error: string;
|
|
17
16
|
ok?: undefined;
|
|
17
|
+
error: string;
|
|
18
18
|
} | {
|
|
19
19
|
error?: undefined;
|
|
20
20
|
ok: boolean;
|
|
@@ -147,6 +147,11 @@ export function buildExtensionHtml(content, themeVars, isDark, extensionId, bind
|
|
|
147
147
|
</style>
|
|
148
148
|
<style>
|
|
149
149
|
*, *::before, *::after { border-color: hsl(var(--border)); }
|
|
150
|
+
/* Alpine only honours x-cloak when a stylesheet hides it, and extension
|
|
151
|
+
content is a body snippet that cannot supply one. Without this, an
|
|
152
|
+
x-cloak overlay paints over the whole extension until Alpine boots —
|
|
153
|
+
and forever if it never does. */
|
|
154
|
+
[x-cloak] { display: none !important; }
|
|
150
155
|
html, body {
|
|
151
156
|
/* Transparent so the iframe inherits the host surface (dashboard panel,
|
|
152
157
|
sidebar, chat) instead of painting the browser's default white canvas.
|
|
@@ -41,23 +41,23 @@ export declare function createObservabilityHandler(): import("h3").EventHandlerW
|
|
|
41
41
|
thumbsUpRate: number;
|
|
42
42
|
avgEvalScore: number;
|
|
43
43
|
} | {
|
|
44
|
+
ok?: undefined;
|
|
44
45
|
error?: undefined;
|
|
45
46
|
summary: import("./types.js").TraceSummary;
|
|
46
47
|
spans: import("./types.js").TraceSpan[];
|
|
47
48
|
id?: undefined;
|
|
48
|
-
ok?: undefined;
|
|
49
49
|
} | {
|
|
50
|
+
ok?: undefined;
|
|
50
51
|
error?: undefined;
|
|
51
52
|
summary?: undefined;
|
|
52
53
|
spans?: undefined;
|
|
53
54
|
id: string;
|
|
54
|
-
ok?: undefined;
|
|
55
55
|
} | {
|
|
56
|
+
ok?: undefined;
|
|
56
57
|
summary?: undefined;
|
|
57
58
|
spans?: undefined;
|
|
58
59
|
id?: undefined;
|
|
59
60
|
error: any;
|
|
60
|
-
ok?: undefined;
|
|
61
61
|
} | {
|
|
62
62
|
error?: undefined;
|
|
63
63
|
summary?: undefined;
|
|
@@ -48,8 +48,8 @@ export declare function handleUpdateResource(event: any): Promise<import("./stor
|
|
|
48
48
|
}>;
|
|
49
49
|
/** DELETE /_agent-native/resources/:id — delete a resource */
|
|
50
50
|
export declare function handleDeleteResource(event: any): Promise<{
|
|
51
|
-
error: string;
|
|
52
51
|
ok?: undefined;
|
|
52
|
+
error: string;
|
|
53
53
|
} | {
|
|
54
54
|
error?: undefined;
|
|
55
55
|
ok: boolean;
|
package/dist/secrets/routes.d.ts
CHANGED
|
@@ -34,16 +34,16 @@ export declare function createListSecretsHandler(): import("h3").EventHandlerWit
|
|
|
34
34
|
/** POST /_agent-native/secrets/:key — write a secret. */
|
|
35
35
|
export declare function createWriteSecretHandler(): import("h3").EventHandlerWithFetch<import("h3").EventHandlerRequest, Promise<{
|
|
36
36
|
error: string;
|
|
37
|
-
status?: undefined;
|
|
38
37
|
ok?: undefined;
|
|
38
|
+
status?: undefined;
|
|
39
39
|
} | {
|
|
40
40
|
ok: boolean;
|
|
41
41
|
status: string;
|
|
42
42
|
error?: undefined;
|
|
43
43
|
} | {
|
|
44
|
+
ok?: undefined;
|
|
44
45
|
error: string;
|
|
45
46
|
removed?: undefined;
|
|
46
|
-
ok?: undefined;
|
|
47
47
|
} | {
|
|
48
48
|
ok: boolean;
|
|
49
49
|
removed: boolean;
|
|
@@ -54,9 +54,9 @@ export declare function createWriteSecretHandler(): import("h3").EventHandlerWit
|
|
|
54
54
|
* or the current stored value without changing anything.
|
|
55
55
|
*/
|
|
56
56
|
export declare function createTestSecretHandler(): import("h3").EventHandlerWithFetch<import("h3").EventHandlerRequest, Promise<{
|
|
57
|
+
ok?: undefined;
|
|
57
58
|
error: string;
|
|
58
59
|
note?: undefined;
|
|
59
|
-
ok?: undefined;
|
|
60
60
|
} | {
|
|
61
61
|
ok: boolean;
|
|
62
62
|
note?: undefined;
|
|
@@ -416,21 +416,22 @@ export function resourceScopeForOwner(owner, currentOwner) {
|
|
|
416
416
|
return "resource";
|
|
417
417
|
}
|
|
418
418
|
async function loadAgentsResourceForPrompt(owner, scope, maxChars = SHARED_PROMPT_RESOURCE_MAX_CHARS) {
|
|
419
|
+
let agents;
|
|
419
420
|
try {
|
|
420
|
-
|
|
421
|
-
if (!agents?.content?.trim())
|
|
422
|
-
return null;
|
|
423
|
-
return promptResourceBlock({
|
|
424
|
-
name: "AGENTS.md",
|
|
425
|
-
scope,
|
|
426
|
-
path: "AGENTS.md",
|
|
427
|
-
content: agents.content,
|
|
428
|
-
maxChars,
|
|
429
|
-
});
|
|
421
|
+
agents = await resourceGetByPath(owner, "AGENTS.md");
|
|
430
422
|
}
|
|
431
|
-
catch {
|
|
432
|
-
|
|
423
|
+
catch (error) {
|
|
424
|
+
throw new Error(`Unable to read durable AGENTS.md instructions for ${scope} (${owner}). The run cannot safely continue without them.`, { cause: error });
|
|
433
425
|
}
|
|
426
|
+
if (!agents?.content?.trim())
|
|
427
|
+
return null;
|
|
428
|
+
return promptResourceBlock({
|
|
429
|
+
name: "AGENTS.md",
|
|
430
|
+
scope,
|
|
431
|
+
path: "AGENTS.md",
|
|
432
|
+
content: agents.content,
|
|
433
|
+
maxChars,
|
|
434
|
+
});
|
|
434
435
|
}
|
|
435
436
|
async function loadInstructionResourcesForPrompt(owner, scope, maxChars = SHARED_PROMPT_RESOURCE_MAX_CHARS, summaryOnly = false) {
|
|
436
437
|
try {
|
|
@@ -671,14 +672,14 @@ export async function loadResourcesForPrompt(owner, compact = false, selfAppId,
|
|
|
671
672
|
// every app in the workspace, not copied into app scopes. They may come from
|
|
672
673
|
// SQL, Dispatch, or local file mode.
|
|
673
674
|
const workspaceAgents = await loadAgentsResourceForPrompt(WORKSPACE_OWNER, "workspace", promptResourceMaxChars);
|
|
674
|
-
addSection(workspaceAgents);
|
|
675
|
+
addSection(workspaceAgents, "required");
|
|
675
676
|
addSections(await loadInstructionResourcesForPrompt(WORKSPACE_OWNER, "workspace-instruction", promptResourceMaxChars, compact));
|
|
676
677
|
const organizationOwner = sharedResourceOwner(orgId);
|
|
677
678
|
// 4. Legacy app-wide defaults. Existing deployments keep their seeded
|
|
678
679
|
// shared guidance as an inherited fallback; organization writes never
|
|
679
680
|
// mutate this owner.
|
|
680
681
|
const appDefaultAgents = await loadAgentsResourceForPrompt(SHARED_OWNER, organizationOwner === SHARED_OWNER ? "shared" : "app-default", promptResourceMaxChars);
|
|
681
|
-
addSection(appDefaultAgents);
|
|
682
|
+
addSection(appDefaultAgents, "required");
|
|
682
683
|
addSections(await loadInstructionResourcesForPrompt(SHARED_OWNER, organizationOwner === SHARED_OWNER
|
|
683
684
|
? "shared-instruction"
|
|
684
685
|
: "app-default-instruction", promptResourceMaxChars, compact));
|
|
@@ -686,14 +687,14 @@ export async function loadResourcesForPrompt(owner, compact = false, selfAppId,
|
|
|
686
687
|
// learnings that Slack/integration runs share with interactive app chat.
|
|
687
688
|
if (organizationOwner !== SHARED_OWNER) {
|
|
688
689
|
const organizationAgents = await loadAgentsResourceForPrompt(organizationOwner, "organization", promptResourceMaxChars);
|
|
689
|
-
addSection(organizationAgents);
|
|
690
|
+
addSection(organizationAgents, "required");
|
|
690
691
|
addSections(await loadInstructionResourcesForPrompt(organizationOwner, "organization-instruction", promptResourceMaxChars, compact));
|
|
691
692
|
}
|
|
692
693
|
// 6. Personal SQL resources. These come last in the instruction stack so a
|
|
693
694
|
// user can narrow or override organization/app and workspace defaults.
|
|
694
695
|
if (owner !== SHARED_OWNER && owner !== WORKSPACE_OWNER) {
|
|
695
696
|
const personalAgents = await loadAgentsResourceForPrompt(owner, "personal", promptResourceMaxChars);
|
|
696
|
-
addSection(personalAgents, "
|
|
697
|
+
addSection(personalAgents, "required");
|
|
697
698
|
addSections(await loadInstructionResourcesForPrompt(owner, "personal-instruction", promptResourceMaxChars, compact), "user");
|
|
698
699
|
}
|
|
699
700
|
const resourceSkillsBlock = await loadResourceSkillsPromptBlock(owner, orgId);
|
|
@@ -16,6 +16,15 @@ export { loadResourcesForPrompt };
|
|
|
16
16
|
export { _agentChatPromptSectionsForTests };
|
|
17
17
|
export { buildPublicAgentA2ASkills };
|
|
18
18
|
export { assembleA2AFinalResponse };
|
|
19
|
+
export declare function buildLeanSystemPrompt(input: {
|
|
20
|
+
basePrompt: string;
|
|
21
|
+
resources: string;
|
|
22
|
+
additionalFramework?: string;
|
|
23
|
+
cacheSplit?: string;
|
|
24
|
+
extra?: string;
|
|
25
|
+
modelOverlay?: string;
|
|
26
|
+
runtimeContext?: string;
|
|
27
|
+
}): string;
|
|
19
28
|
export type { AgentChatPluginOptions };
|
|
20
29
|
export { runA2AAgentLoop };
|
|
21
30
|
export { runMCPAgentLoop };
|