@agent-native/core 0.148.1 → 0.149.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/changelog/2026-08-10-wide-tables-in-analytics-chat-now-scroll-horizontally-within.md +6 -0
- package/corpus/templates/calendar/app/components/calendar/DayView.tsx +13 -53
- package/corpus/templates/calendar/app/components/calendar/WeekView.tsx +11 -70
- package/corpus/templates/calendar/app/lib/event-layout.ts +122 -0
- package/corpus/templates/calendar/app/routes/_app.availability.tsx +1 -1
- package/corpus/templates/calendar/changelog/2026-08-10-opening-availability-settings-from-the-agent-lands-on-the-av.md +6 -0
- package/corpus/templates/calendar/vitest.config.ts +6 -1
- package/corpus/templates/clips/actions/lib/audio-only-transcription.ts +3 -1
- package/corpus/templates/clips/app/components/player/video-player.tsx +44 -4
- package/corpus/templates/clips/changelog/2026-08-10-fixed-transcription-failures-for-recordings-without-captured.md +6 -0
- package/corpus/templates/clips/changelog/2026-08-10-mobile-clips-can-now-enter-fullscreen-on-iphone-safari.md +6 -0
- package/corpus/templates/content/actions/_property-utils.ts +11 -1
- package/corpus/templates/content/actions/view-screen.ts +62 -12
- package/corpus/templates/content/server/plugins/agent-chat.ts +2 -0
- package/corpus/templates/design/.agents/skills/design-templates/SKILL.md +22 -0
- package/corpus/templates/design/AGENTS.md +3 -0
- package/corpus/templates/design/actions/create-design-from-template.ts +19 -0
- package/corpus/templates/design/actions/get-design-snapshot.ts +18 -0
- package/corpus/templates/design/actions/get-design-template.ts +178 -0
- package/corpus/templates/design/actions/list-designs.ts +3 -1
- package/corpus/templates/design/actions/view-screen.ts +31 -0
- package/corpus/templates/design/app/components/design/MultiScreenCanvas.tsx +225 -214
- package/corpus/templates/design/app/components/design/multi-screen/types.ts +3 -0
- package/corpus/templates/design/app/i18n-data.ts +78 -0
- package/corpus/templates/design/app/lib/design-authors.ts +64 -0
- package/corpus/templates/design/app/pages/Index.tsx +114 -4
- package/corpus/templates/design/app/pages/design-editor/generation-prompt-directives.ts +1 -0
- package/corpus/templates/design/changelog/2026-08-07-alt-dragging-an-element-to-copy-it-now-keeps-the-copy-visibl.md +6 -0
- package/corpus/templates/design/changelog/2026-08-07-design-cards-now-show-who-created-each-design-with-a-filter-.md +6 -0
- package/corpus/templates/design/changelog/2026-08-07-drawing-a-shape-on-the-overview-canvas-now-keeps-the-shape-s.md +6 -0
- package/corpus/templates/design/changelog/2026-08-07-hold-option-alt-while-dragging-a-frame-on-the-overview-canva.md +6 -0
- package/corpus/templates/design/server/lib/design-template-data.ts +143 -0
- package/corpus/templates/design/server/plugins/agent-chat.ts +1 -0
- package/corpus/templates/forms/AGENTS.md +2 -2
- package/corpus/templates/forms/actions/create-form.ts +1 -1
- package/corpus/templates/forms/actions/update-form.ts +5 -5
- package/corpus/templates/forms/changelog/2026-08-10-forms-now-keep-agent-applied-field-changes-visible-after-an-.md +6 -0
- package/corpus/templates/forms/changelog/2026-08-10-published-form-links-always-use-the-working-public-form-url.md +6 -0
- package/corpus/templates/forms/server/plugins/agent-chat.ts +2 -2
- package/corpus/templates/slides/AGENTS.md +4 -3
- package/corpus/templates/slides/actions/import-google-slides-reference.ts +56 -10
- package/corpus/templates/slides/actions/patch-deck.ts +18 -2
- package/corpus/templates/slides/app/components/deck/SlideRenderer.tsx +46 -0
- package/corpus/templates/slides/app/components/editor/BlockBubbleMenu.tsx +194 -3
- package/corpus/templates/slides/app/components/editor/EditorSidebar.tsx +22 -75
- package/corpus/templates/slides/app/components/editor/ExportMenu.tsx +5 -3
- package/corpus/templates/slides/app/components/editor/GeneratingSlidePreview.tsx +5 -1
- package/corpus/templates/slides/app/components/editor/GoogleDriveConnectionCta.tsx +15 -4
- package/corpus/templates/slides/app/components/editor/NewDeckReferenceStep.tsx +116 -55
- package/corpus/templates/slides/app/components/editor/SlideEditor.tsx +27 -4
- package/corpus/templates/slides/app/components/editor/slide-object-interactions.ts +45 -0
- package/corpus/templates/slides/app/components/onboarding/FirstDeckOnboardingFlow.tsx +143 -18
- package/corpus/templates/slides/app/i18n/en-US.ts +6 -0
- package/corpus/templates/slides/app/lib/export-pdf-client.ts +84 -25
- package/corpus/templates/slides/app/lib/generation-state.ts +7 -1
- package/corpus/templates/slides/app/lib/import-uploaded-deck.ts +11 -0
- package/corpus/templates/slides/app/pages/DeckEditor.tsx +44 -14
- package/corpus/templates/slides/app/pages/Index.tsx +124 -135
- package/corpus/templates/slides/changelog/2026-08-08-google-slides-export-now-tells-you-why-a-deck-fell-back-to-a.md +6 -0
- package/corpus/templates/slides/changelog/2026-08-09-delete-key-now-removes-a-selected-image.md +6 -0
- package/corpus/templates/slides/changelog/2026-08-09-editing-a-slide-in-an-imported-deck-no-longer-fails-to-save.md +6 -0
- package/corpus/templates/slides/changelog/2026-08-09-fixed-pdf-and-custom-size-powerpoint-imports-rendering-with-.md +6 -0
- package/corpus/templates/slides/changelog/2026-08-09-images-from-sites-without-cors-no-longer-export-blank.md +6 -0
- package/corpus/templates/slides/changelog/2026-08-09-imported-pdf-headings-no-longer-lose-the-space-between-color.md +6 -0
- package/corpus/templates/slides/changelog/2026-08-09-imported-slide-text-no-longer-renders-too-large-for-its-box.md +6 -0
- package/corpus/templates/slides/changelog/2026-08-09-large-decks-no-longer-render-slowly-or-glitch-in-the-editor.md +6 -0
- package/corpus/templates/slides/changelog/2026-08-09-revise-highlighted-slide-text-with-ai.md +6 -0
- package/corpus/templates/slides/changelog/2026-08-09-the-deck-editor-no-longer-stays-dimmed-after-the-window-narro.md +6 -0
- package/corpus/templates/slides/changelog/2026-08-10-imported-reference-decks-now-show-clear-success-and-stay-sel.md +6 -0
- package/corpus/templates/slides/changelog/2026-08-10-pasted-google-slides-links-import-after-reconnecting-google-.md +6 -0
- package/corpus/templates/slides/server/handlers/google-docs-auth.ts +4 -0
- package/corpus/templates/slides/server/handlers/import/html-converter.ts +115 -22
- package/corpus/templates/slides/server/handlers/import/pdf-fidelity-parser.ts +11 -2
- package/corpus/templates/slides/server/lib/fetch-remote-image.ts +192 -0
- package/corpus/templates/slides/server/lib/google-docs-oauth.ts +13 -0
- package/corpus/templates/slides/server/lib/image-proxy-url.ts +192 -0
- package/corpus/templates/slides/server/plugins/agent-chat.ts +1 -1
- package/corpus/templates/slides/server/routes/api/image-proxy.get.ts +65 -0
- package/dist/agent/engine/registry.d.ts +8 -2
- package/dist/agent/engine/registry.js +63 -29
- package/dist/agent/production-agent.js +7 -0
- package/dist/agent/run-manager.d.ts +5 -4
- package/dist/agent/run-manager.js +6 -5
- package/dist/cli/claude-code-participant.d.ts +2 -1
- package/dist/cli/claude-code-participant.js +19 -0
- package/dist/cli/code-agent-executor.js +223 -0
- package/dist/cli/create-workspace.js +3 -3
- package/dist/cli/create.d.ts +3 -2
- package/dist/cli/create.js +20 -24
- package/dist/client/AgentPanel.js +8 -4
- package/dist/client/AssistantChat.js +34 -1
- package/dist/client/agent-chat-adapter.d.ts +1 -0
- package/dist/client/agent-chat-adapter.js +10 -2
- package/dist/client/chat/markdown-renderer.d.ts +1 -0
- package/dist/client/chat/markdown-renderer.js +4 -0
- package/dist/client/chat/message-components.d.ts +1 -0
- package/dist/client/chat/message-components.js +9 -1
- package/dist/client/chat/tool-call-display.d.ts +8 -0
- package/dist/client/chat/tool-call-display.js +30 -21
- package/dist/client/chat-first/app-pane.js +1 -1
- package/dist/client/chat-first/apps-rail.d.ts +1 -1
- package/dist/client/chat-first/apps-rail.js +11 -11
- package/dist/client/chat-first/chat-history.d.ts +1 -1
- package/dist/client/chat-first/chat-history.js +2 -0
- package/dist/client/chat-first/primary-nav.js +1 -1
- package/dist/client/progress/RunsTray.js +14 -1
- package/dist/client/resources/McpConnectionSuggestion.js +2 -2
- package/dist/client/settings/SettingsTabsPage.d.ts +3 -1
- package/dist/client/settings/SettingsTabsPage.js +2 -2
- package/dist/client/sse-event-processor.d.ts +8 -0
- package/dist/client/sse-event-processor.js +13 -6
- package/dist/collab/awareness.d.ts +2 -2
- package/dist/collab/routes.d.ts +1 -1
- package/dist/deploy/build.d.ts +5 -7
- package/dist/deploy/build.js +19 -12
- package/dist/localization/default-messages.js +1 -1
- package/dist/notifications/routes.d.ts +3 -3
- package/dist/observability/routes.d.ts +6 -6
- package/dist/provider-api/actions/provider-api.d.ts +2 -2
- package/dist/scripts/call-agent.js +3 -3
- package/dist/scripts/describe-workspace-apps.js +1 -1
- package/dist/server/agent-capabilities.js +0 -0
- package/dist/server/agent-chat/context-tools.js +1 -1
- package/dist/server/agent-chat/prompt-resources.js +1 -1
- package/dist/server/agent-chat-plugin.js +1 -1
- package/dist/server/auth.js +190 -42
- package/dist/server/better-auth-migrations.js +53 -0
- package/dist/server/http-response-telemetry.js +7 -1
- package/dist/server/onboarding-html.js +119 -33
- package/dist/server/transcribe-voice.d.ts +1 -1
- package/dist/shared/password-policy.d.ts +2 -1
- package/dist/shared/password-policy.js +2 -1
- package/dist/styles/agent-conversation.css +20 -3
- package/dist/styles/agent-native.css +14 -2
- package/dist/templates/default/app/i18n/ar-SA.ts +1 -1
- package/dist/templates/default/app/i18n/de-DE.ts +1 -1
- package/dist/templates/default/app/i18n/en-US.ts +1 -1
- package/dist/templates/default/app/i18n/es-ES.ts +1 -1
- package/dist/templates/default/app/i18n/fr-FR.ts +1 -1
- package/dist/templates/default/app/i18n/hi-IN.ts +1 -1
- package/dist/templates/default/app/i18n/ja-JP.ts +1 -1
- package/dist/templates/default/app/i18n/ko-KR.ts +1 -1
- package/dist/templates/default/app/i18n/pt-BR.ts +1 -1
- package/dist/templates/default/app/i18n/zh-CN.ts +1 -1
- package/dist/templates/default/app/i18n/zh-TW.ts +1 -1
- package/dist/templates/default/pnpm-workspace.yaml +1 -0
- package/dist/templates/workspace-root/pnpm-workspace.yaml +2 -0
- package/docs/content/cloneable-saas.mdx +6 -6
- package/docs/content/deployment.mdx +10 -8
- package/docs/content/environment-variables.mdx +4 -3
- package/package.json +2 -2
- package/src/templates/default/app/i18n/ar-SA.ts +1 -1
- package/src/templates/default/app/i18n/de-DE.ts +1 -1
- package/src/templates/default/app/i18n/en-US.ts +1 -1
- package/src/templates/default/app/i18n/es-ES.ts +1 -1
- package/src/templates/default/app/i18n/fr-FR.ts +1 -1
- package/src/templates/default/app/i18n/hi-IN.ts +1 -1
- package/src/templates/default/app/i18n/ja-JP.ts +1 -1
- package/src/templates/default/app/i18n/ko-KR.ts +1 -1
- package/src/templates/default/app/i18n/pt-BR.ts +1 -1
- package/src/templates/default/app/i18n/zh-CN.ts +1 -1
- package/src/templates/default/app/i18n/zh-TW.ts +1 -1
- package/src/templates/default/pnpm-workspace.yaml +1 -0
- package/src/templates/workspace-root/pnpm-workspace.yaml +2 -0
|
@@ -75,6 +75,7 @@ function prepareToolStackExitClone(clone, snapshot) {
|
|
|
75
75
|
export function ToolCallStackMotion({ children, className, }) {
|
|
76
76
|
const stackRef = useRef(null);
|
|
77
77
|
const previousRef = useRef(new Map());
|
|
78
|
+
const previousStructureRef = useRef([]);
|
|
78
79
|
const activeMotionsRef = useRef(new Map());
|
|
79
80
|
const exitAnimationsRef = useRef(new Map());
|
|
80
81
|
useLayoutEffect(() => {
|
|
@@ -104,6 +105,11 @@ export function ToolCallStackMotion({ children, className, }) {
|
|
|
104
105
|
}
|
|
105
106
|
exitAnimationsRef.current.clear();
|
|
106
107
|
const elements = Array.from(stack.querySelectorAll("[data-agent-tool-call-id], [data-agent-tool-summary]"));
|
|
108
|
+
const structure = elements.map((element, index) => toolStackMotionKey(element, index));
|
|
109
|
+
const previousStructure = previousStructureRef.current;
|
|
110
|
+
const structureChanged = structure.length !== previousStructure.length ||
|
|
111
|
+
structure.some((key, index) => key !== previousStructure[index]);
|
|
112
|
+
previousStructureRef.current = structure;
|
|
107
113
|
const current = new Map();
|
|
108
114
|
for (const [index, element] of elements.entries()) {
|
|
109
115
|
const rect = element.getBoundingClientRect();
|
|
@@ -116,7 +122,11 @@ export function ToolCallStackMotion({ children, className, }) {
|
|
|
116
122
|
});
|
|
117
123
|
}
|
|
118
124
|
previousRef.current = current;
|
|
119
|
-
|
|
125
|
+
// Entry motion changes the measured transform without changing the stack
|
|
126
|
+
// structure. Do not turn that animation's cleanup into a second FLIP pass.
|
|
127
|
+
if (previous.size === 0 ||
|
|
128
|
+
!structureChanged ||
|
|
129
|
+
prefersReducedMotionForToolStack())
|
|
120
130
|
return;
|
|
121
131
|
const summary = elements.find((element) => element.dataset.agentToolSummary !== undefined);
|
|
122
132
|
const summaryRect = summary?.getBoundingClientRect();
|
|
@@ -227,13 +237,6 @@ export function ToolActivityPresentation({ toolName, isRunning, isActiveTail, to
|
|
|
227
237
|
// Presentation follows the active chat tail rather than execution state so
|
|
228
238
|
// that newly revealed completed tools still get their entrance motion.
|
|
229
239
|
const [animateEntry, setAnimateEntry] = useState(isActiveTail);
|
|
230
|
-
const previousActiveTailRef = useRef(isActiveTail);
|
|
231
|
-
useEffect(() => {
|
|
232
|
-
if (isActiveTail && !previousActiveTailRef.current) {
|
|
233
|
-
setAnimateEntry(true);
|
|
234
|
-
}
|
|
235
|
-
previousActiveTailRef.current = isActiveTail;
|
|
236
|
-
}, [isActiveTail]);
|
|
237
240
|
useEffect(() => {
|
|
238
241
|
if (!animateEntry)
|
|
239
242
|
return;
|
|
@@ -438,29 +441,35 @@ export function AnimatedCollapse({ open, children, }) {
|
|
|
438
441
|
* turn. Approve re-issues the turn with the call's `approvalKey`; Deny dismisses
|
|
439
442
|
* the prompt locally (the action stays un-run).
|
|
440
443
|
*/
|
|
441
|
-
function ApprovalAffordance({ toolName, approval, }) {
|
|
444
|
+
function ApprovalAffordance({ toolName, toolCallId, approval, }) {
|
|
442
445
|
const ctx = React.useContext(ApprovalContext);
|
|
443
|
-
const [
|
|
444
|
-
const
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
446
|
+
const [localResolution, setLocalResolution] = useState(null);
|
|
447
|
+
const retainedResolution = ctx?.getApprovalResolution?.(approval.approvalKey, toolCallId) ?? null;
|
|
448
|
+
const resolution = retainedResolution ??
|
|
449
|
+
localResolution ??
|
|
450
|
+
(approval.dismissed === true ? "denied" : null);
|
|
451
|
+
// Once resolved, collapse to a quiet note so a repository refresh cannot
|
|
452
|
+
// restore the action buttons while the continuation is running.
|
|
453
|
+
if (resolution === "approved") {
|
|
448
454
|
return (_jsxs("div", { className: "mt-1.5 text-xs text-muted-foreground", children: ["Approved. Re-running ", toolName, "..."] }));
|
|
449
455
|
}
|
|
450
456
|
// Deny defaults to local-only (the action simply stays un-run). When the
|
|
451
457
|
// host also provided `onDeny` (e.g. a Code session resolving its own
|
|
452
458
|
// pending approval), it fires alongside the local state.
|
|
453
|
-
if (denied) {
|
|
459
|
+
if (resolution === "denied") {
|
|
454
460
|
return (_jsxs("div", { className: "mt-1.5 text-xs text-muted-foreground", children: ["Denied. ", toolName, " did not run."] }));
|
|
455
461
|
}
|
|
456
462
|
return (_jsxs("div", { className: "mt-1.5 flex items-center gap-2 rounded-md border border-border bg-muted/40 px-2.5 py-1.5", children: [_jsx(IconShieldCheck, { className: "h-3.5 w-3.5 shrink-0 text-muted-foreground" }), _jsxs("span", { className: "mr-auto text-xs text-muted-foreground", children: ["Approve to run ", toolName, "?"] }), ctx && (_jsxs("button", { type: "button", onClick: () => {
|
|
457
|
-
|
|
463
|
+
setLocalResolution("approved");
|
|
464
|
+
ctx.onApprovalResolved?.(approval.approvalKey, "approved", toolCallId);
|
|
458
465
|
ctx.onApprove(approval.approvalKey);
|
|
459
466
|
}, className: cn("inline-flex items-center gap-1 rounded-md px-2.5 py-1 text-xs font-medium transition-colors", "bg-foreground text-background hover:bg-foreground/90"), children: [_jsx(IconCheck, { className: "h-3.5 w-3.5" }), "Approve"] })), ctx?.onAlwaysAllow && (_jsxs("button", { type: "button", onClick: () => {
|
|
460
|
-
|
|
467
|
+
setLocalResolution("approved");
|
|
468
|
+
ctx.onApprovalResolved?.(approval.approvalKey, "approved", toolCallId);
|
|
461
469
|
ctx.onAlwaysAllow?.(approval.approvalKey);
|
|
462
470
|
}, title: "Approve and always allow this exact command", 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(IconShieldCheck, { className: "h-3.5 w-3.5" }), "Always allow"] })), _jsxs("button", { type: "button", onClick: () => {
|
|
463
|
-
|
|
471
|
+
setLocalResolution("denied");
|
|
472
|
+
ctx?.onApprovalResolved?.(approval.approvalKey, "denied", toolCallId);
|
|
464
473
|
ctx?.onDeny?.(approval.approvalKey);
|
|
465
474
|
}, 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"] })] }));
|
|
466
475
|
}
|
|
@@ -481,9 +490,9 @@ export function ToolCallDisplay({ toolName, toolCallId, argsText, args, result,
|
|
|
481
490
|
if (toolKind === "write") {
|
|
482
491
|
return wrapToolDisplay(_jsx(WriteCell, { meta: structuredMeta, isRunning: isRunning }));
|
|
483
492
|
}
|
|
484
|
-
return wrapToolDisplay(_jsx(ToolCallDisplayGeneric, { toolName: toolName, argsText: argsText, args: args, result: result, mcpApp: mcpApp, chatUI: chatUI, isRunning: isRunning, outcome: outcome, isActiveTail: showActiveTail, structuredMeta: structuredMeta, approval: approval, repeatCount: repeatCount }));
|
|
493
|
+
return wrapToolDisplay(_jsx(ToolCallDisplayGeneric, { toolName: toolName, toolCallId: toolCallId, argsText: argsText, args: args, result: result, mcpApp: mcpApp, chatUI: chatUI, isRunning: isRunning, outcome: outcome, isActiveTail: showActiveTail, structuredMeta: structuredMeta, approval: approval, repeatCount: repeatCount }));
|
|
485
494
|
}
|
|
486
|
-
function ToolCallDisplayGeneric({ toolName, argsText, args, result, mcpApp, chatUI, isRunning, outcome, isActiveTail, structuredMeta, approval, repeatCount, }) {
|
|
495
|
+
function ToolCallDisplayGeneric({ toolName, toolCallId, argsText, args, result, mcpApp, chatUI, isRunning, outcome, isActiveTail, structuredMeta, approval, repeatCount, }) {
|
|
487
496
|
const isRawCallAgent = toolName === "call-agent";
|
|
488
497
|
const isAgentCall = toolName.startsWith("agent:") || isRawCallAgent;
|
|
489
498
|
const [expanded, setExpanded] = useState(isAgentCall);
|
|
@@ -585,7 +594,7 @@ function ToolCallDisplayGeneric({ toolName, argsText, args, result, mcpApp, chat
|
|
|
585
594
|
? structuredMeta.agentDurationMs
|
|
586
595
|
: agentActivity?.durationMs }));
|
|
587
596
|
}
|
|
588
|
-
return (_jsxs("div", { className: "group/tool my-0.5 w-full overflow-hidden", children: [mcpApp && _jsx(McpAppRenderer, { app: mcpApp, className: "mb-1.5" }), _jsxs("button", { type: "button", onClick: () => canExpand && setExpanded(!isExpanded), "aria-expanded": canExpand ? isExpanded : undefined, className: cn("flex w-full items-center gap-1.5 rounded-md py-0.5 text-left text-[13px] text-muted-foreground transition-colors", canExpand && "hover:text-foreground", isRunning && "text-muted-foreground"), children: [_jsx("span", { className: "relative flex size-4 shrink-0 items-center justify-center", children: isRunning ? (_jsx(IconLoader2, { className: "size-3.5 animate-spin" })) : isAgentError ? (_jsx(IconCircleX, { className: "size-3.5 text-destructive" })) : isUnknownOutcome ? (_jsx(IconAlertTriangle, { className: "size-3.5 text-muted-foreground" })) : (_jsxs(_Fragment, { children: [_jsx(ToolIcon, { className: cn("size-3.5 transition-opacity", canExpand && "group-hover/tool:opacity-0") }), canExpand && (_jsx(IconChevronRight, { className: cn("absolute size-3.5 opacity-0 transition-[opacity,transform] group-hover/tool:opacity-100", isExpanded && "rotate-90") }))] })) }), _jsx("span", { className: cn("min-w-0 truncate font-normal", isActiveTail && "agent-running-shimmer"), children: displayName }), repeatCount && repeatCount > 1 && (_jsxs("span", { className: "shrink-0 rounded border border-border/60 px-1.5 py-0.5 text-[10px] leading-none text-muted-foreground", title: `Repeated ${repeatCount} times`, children: [repeatCount, "x"] }))] }), _jsx(AnimatedCollapse, { open: isExpanded && !isAgentCall && (hasArgs || result !== undefined), children: _jsxs("div", { className: "mt-1 space-y-2 pl-5", children: [inputPayload && (_jsx(SimpleCodeViewer, { text: inputPayload.text, lang: inputPayload.lang })), resultPayload && (_jsx(ToolOutputPopover, { open: outputOpen, onOpenChange: setOutputOpen, title: outputTitle, payload: resultPayload, children: _jsx("button", { type: "button", "aria-label": `View ${toolName} output`, className: "inline-flex size-6 items-center justify-center rounded-md text-muted-foreground/70 transition-colors hover:bg-accent hover:text-foreground", children: _jsx(IconCode, { className: "size-3.5" }) }) }))] }) }), isUnknownOutcome && (_jsx("p", { role: "status", className: "ps-5 text-xs text-muted-foreground", children: "Interrupted before this finished reporting \u2014 it may or may not have completed. Check before retrying." })), approval && (_jsx(ApprovalAffordance, { toolName: toolName, approval: approval }))] }));
|
|
597
|
+
return (_jsxs("div", { className: "group/tool my-0.5 w-full overflow-hidden", children: [mcpApp && _jsx(McpAppRenderer, { app: mcpApp, className: "mb-1.5" }), _jsxs("button", { type: "button", onClick: () => canExpand && setExpanded(!isExpanded), "aria-expanded": canExpand ? isExpanded : undefined, className: cn("flex w-full items-center gap-1.5 rounded-md py-0.5 text-left text-[13px] text-muted-foreground transition-colors", canExpand && "hover:text-foreground", isRunning && "text-muted-foreground"), children: [_jsx("span", { className: "relative flex size-4 shrink-0 items-center justify-center", children: isRunning ? (_jsx(IconLoader2, { className: "size-3.5 animate-spin" })) : isAgentError ? (_jsx(IconCircleX, { className: "size-3.5 text-destructive" })) : isUnknownOutcome ? (_jsx(IconAlertTriangle, { className: "size-3.5 text-muted-foreground" })) : (_jsxs(_Fragment, { children: [_jsx(ToolIcon, { className: cn("size-3.5 transition-opacity", canExpand && "group-hover/tool:opacity-0") }), canExpand && (_jsx(IconChevronRight, { className: cn("absolute size-3.5 opacity-0 transition-[opacity,transform] group-hover/tool:opacity-100", isExpanded && "rotate-90") }))] })) }), _jsx("span", { className: cn("min-w-0 truncate font-normal", isActiveTail && "agent-running-shimmer"), children: displayName }), repeatCount && repeatCount > 1 && (_jsxs("span", { className: "shrink-0 rounded border border-border/60 px-1.5 py-0.5 text-[10px] leading-none text-muted-foreground", title: `Repeated ${repeatCount} times`, children: [repeatCount, "x"] }))] }), _jsx(AnimatedCollapse, { open: isExpanded && !isAgentCall && (hasArgs || result !== undefined), children: _jsxs("div", { className: "mt-1 space-y-2 pl-5", children: [inputPayload && (_jsx(SimpleCodeViewer, { text: inputPayload.text, lang: inputPayload.lang })), resultPayload && (_jsx(ToolOutputPopover, { open: outputOpen, onOpenChange: setOutputOpen, title: outputTitle, payload: resultPayload, children: _jsx("button", { type: "button", "aria-label": `View ${toolName} output`, className: "inline-flex size-6 items-center justify-center rounded-md text-muted-foreground/70 transition-colors hover:bg-accent hover:text-foreground", children: _jsx(IconCode, { className: "size-3.5" }) }) }))] }) }), isUnknownOutcome && (_jsx("p", { role: "status", className: "ps-5 text-xs text-muted-foreground", children: "Interrupted before this finished reporting \u2014 it may or may not have completed. Check before retrying." })), approval && (_jsx(ApprovalAffordance, { toolName: toolName, toolCallId: toolCallId, approval: approval }))] }));
|
|
589
598
|
}
|
|
590
599
|
function AgentCallCell({ agentName, activity, progress, responseText, isRunning, isError, durationMs, }) {
|
|
591
600
|
const t = useT();
|
|
@@ -2,5 +2,5 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
2
2
|
import { Skeleton } from "@agent-native/toolkit/ui";
|
|
3
3
|
import { defaultChatFirstCopy } from "./copy.js";
|
|
4
4
|
export function ChatFirstAppPane({ app, status, embedUrl, errorMessage, onRetry, renderEmbed, copy = defaultChatFirstCopy, }) {
|
|
5
|
-
return (_jsx("section", { "data-chat-first-app-pane": true, className: "flex h-full min-h-0 w-full flex-col overflow-hidden bg-background", "aria-label": app ? `${app.name} app` : copy("appUnavailable"), children: status === "loading" ? (_jsxs("div", { className: "space-y-3 p-4", children: [_jsx(Skeleton, { className: "h-5 w-40" }), _jsx(Skeleton, { className: "h-4 w-full" }), _jsx(Skeleton, { className: "h-4 w-2/3" })] })) : status === "ready" && app && embedUrl ? (_jsx("div", { className: "
|
|
5
|
+
return (_jsx("section", { "data-chat-first-app-pane": true, className: "flex h-full min-h-0 w-full flex-col overflow-hidden bg-background", "aria-label": app ? `${app.name} app` : copy("appUnavailable"), children: status === "loading" ? (_jsxs("div", { className: "space-y-3 p-4", children: [_jsx(Skeleton, { className: "h-5 w-40" }), _jsx(Skeleton, { className: "h-4 w-full" }), _jsx(Skeleton, { className: "h-4 w-2/3" })] })) : status === "ready" && app && embedUrl ? (_jsx("div", { className: "min-h-0 flex-1 overflow-hidden", children: renderEmbed({ url: embedUrl, title: app.name }) })) : status === "error" ? (_jsxs("div", { className: "flex h-full flex-col items-center justify-center gap-3 p-6 text-center", children: [_jsx("p", { className: "text-sm text-muted-foreground", children: errorMessage || copy("appUnavailable") }), onRetry ? (_jsx("button", { type: "button", className: "rounded-md border border-border px-3 py-1.5 text-xs text-foreground hover:bg-accent", onClick: onRetry, children: copy("retry") })) : null] })) : (_jsx("div", { className: "flex h-full items-center justify-center p-6 text-center text-sm text-muted-foreground", children: copy("appUnavailable") })) }));
|
|
6
6
|
}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import type { ChatFirstAppRailProps } from "./types.js";
|
|
2
|
-
export declare
|
|
2
|
+
export declare const ChatFirstAppsRail: import("react").MemoExoticComponent<({ apps, activeAppId, loading, error, collapsed, layout: controlledLayout, onLayoutChange, onLayoutError, onRetry, onOpenApp, onOpenAllApps, onCreateApp, createAppTrigger, renderIcon, copy, }: ChatFirstAppRailProps) => import("react").JSX.Element>;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { ContextMenu, ContextMenuContent, ContextMenuItem, ContextMenuSeparator, ContextMenuTrigger, Skeleton, Tooltip, TooltipContent, TooltipTrigger, } from "@agent-native/toolkit/ui";
|
|
3
3
|
import { IconApps, IconChevronDown, IconChevronUp, IconPin, IconPlus, } from "@tabler/icons-react";
|
|
4
|
-
import { useMemo, useState } from "react";
|
|
4
|
+
import { memo, useMemo, useState } from "react";
|
|
5
5
|
import { orderChatFirstAppIds, readChatFirstAppLayout, writeChatFirstAppLayout, } from "../chat-first.js";
|
|
6
6
|
import { cn } from "../utils.js";
|
|
7
7
|
import { defaultChatFirstCopy } from "./copy.js";
|
|
@@ -11,16 +11,16 @@ function AppRows({ apps, activeAppId, layout, onDragStart, onDrop, onDragEnd, on
|
|
|
11
11
|
const orderedApps = orderedIds
|
|
12
12
|
.map((id) => appsById.get(id))
|
|
13
13
|
.filter((app) => Boolean(app));
|
|
14
|
-
return (_jsx("ul", { className: "space-y-
|
|
14
|
+
return (_jsx("ul", { className: "space-y-1", children: orderedApps.map((app) => {
|
|
15
15
|
const active = activeAppId === app.id;
|
|
16
16
|
const pinned = layout.pinnedIds.includes(app.id);
|
|
17
17
|
const index = orderedApps.indexOf(app);
|
|
18
|
-
return (_jsxs(ContextMenu, { children: [_jsx(ContextMenuTrigger, { asChild: true, children: _jsxs("li", { draggable: true, "data-chat-first-app": true, "data-app-id": app.id, className: cn("group flex h-
|
|
18
|
+
return (_jsxs(ContextMenu, { children: [_jsx(ContextMenuTrigger, { asChild: true, children: _jsxs("li", { draggable: true, "data-chat-first-app": true, "data-app-id": app.id, className: cn("group flex h-8 w-full min-w-0 items-center gap-1 rounded-md px-1 text-sm", active
|
|
19
19
|
? "bg-sidebar-accent font-medium text-sidebar-accent-foreground"
|
|
20
20
|
: "text-sidebar-foreground/75 hover:bg-sidebar-accent hover:text-sidebar-accent-foreground"), onDragStart: (event) => {
|
|
21
21
|
event.dataTransfer.effectAllowed = "move";
|
|
22
22
|
onDragStart(app.id);
|
|
23
|
-
}, onDragOver: (event) => event.preventDefault(), onDrop: () => onDrop(app.id), onDragEnd: onDragEnd, children: [_jsxs("button", { type: "button", className: "flex min-w-0 flex-1 items-center gap-2 px-1 text-start", onClick: () => onOpenApp(app), onKeyDown: (event) => {
|
|
23
|
+
}, onDragOver: (event) => event.preventDefault(), onDrop: () => onDrop(app.id), onDragEnd: onDragEnd, children: [_jsxs("button", { type: "button", className: "flex h-full min-w-0 flex-1 items-center gap-2 px-1 text-start", onClick: () => onOpenApp(app), onKeyDown: (event) => {
|
|
24
24
|
if (!event.altKey)
|
|
25
25
|
return;
|
|
26
26
|
if (event.key === "ArrowUp") {
|
|
@@ -31,12 +31,12 @@ function AppRows({ apps, activeAppId, layout, onDragStart, onDrop, onDragEnd, on
|
|
|
31
31
|
event.preventDefault();
|
|
32
32
|
onMove(app.id, 1);
|
|
33
33
|
}
|
|
34
|
-
}, "aria-keyshortcuts": "Alt+ArrowUp Alt+ArrowDown", "aria-label": copy("openApp", { name: app.name }),
|
|
34
|
+
}, "aria-keyshortcuts": "Alt+ArrowUp Alt+ArrowDown", "aria-label": copy("openApp", { name: app.name }), children: [renderIcon(app), _jsx("span", { className: "truncate", children: app.name })] }), _jsx("button", { type: "button", className: cn("flex size-6 shrink-0 items-center justify-center rounded text-sidebar-foreground/45 opacity-0 hover:bg-sidebar-accent hover:text-sidebar-foreground group-hover:opacity-100 focus-visible:opacity-100", pinned && "text-sidebar-foreground/70 opacity-100"), "aria-label": copy(pinned ? "unpinApp" : "pinApp", {
|
|
35
35
|
name: app.name,
|
|
36
|
-
}), "aria-pressed": pinned,
|
|
36
|
+
}), "aria-pressed": pinned, onClick: () => onTogglePinned(app.id), children: _jsx(IconPin, { size: 13, strokeWidth: pinned ? 2.2 : 1.6, "aria-hidden": "true" }) }), _jsx("span", { className: "sr-only", children: `${index + 1} of ${orderedApps.length}` })] }) }), _jsxs(ContextMenuContent, { children: [_jsxs(ContextMenuItem, { onSelect: () => onTogglePinned(app.id), children: [_jsx(IconPin, { size: 14, "aria-hidden": "true" }), pinned ? copy("removePinned") : copy("pinTop")] }), _jsx(ContextMenuSeparator, {}), _jsxs(ContextMenuItem, { disabled: index === 0, onSelect: () => onMove(app.id, -1), children: [_jsx(IconChevronUp, { size: 14, "aria-hidden": "true" }), copy("moveUp")] }), _jsxs(ContextMenuItem, { disabled: index === orderedApps.length - 1, onSelect: () => onMove(app.id, 1), children: [_jsx(IconChevronDown, { size: 14, "aria-hidden": "true" }), copy("moveDown")] })] })] }, app.id));
|
|
37
37
|
}) }));
|
|
38
38
|
}
|
|
39
|
-
export function ChatFirstAppsRail({ apps, activeAppId, loading = false, error, collapsed = false, layout: controlledLayout, onLayoutChange, onLayoutError, onRetry, onOpenApp, onOpenAllApps, onCreateApp, createAppTrigger, renderIcon, copy = defaultChatFirstCopy, }) {
|
|
39
|
+
export const ChatFirstAppsRail = memo(function ChatFirstAppsRail({ apps, activeAppId, loading = false, error, collapsed = false, layout: controlledLayout, onLayoutChange, onLayoutError, onRetry, onOpenApp, onOpenAllApps, onCreateApp, createAppTrigger, renderIcon, copy = defaultChatFirstCopy, }) {
|
|
40
40
|
const [localLayout, setLocalLayout] = useState(() => readChatFirstAppLayout());
|
|
41
41
|
const layout = controlledLayout ?? localLayout;
|
|
42
42
|
const [draggedAppId, setDraggedAppId] = useState(null);
|
|
@@ -95,9 +95,9 @@ export function ChatFirstAppsRail({ apps, activeAppId, loading = false, error, c
|
|
|
95
95
|
if (collapsed) {
|
|
96
96
|
return (_jsxs("section", { "data-chat-first-apps-rail": true, className: "flex flex-col items-center gap-1 px-1.5 pt-2", "aria-label": copy("workspaceApps"), children: [createTrigger, loading && apps.length === 0
|
|
97
97
|
? [0, 1, 2].map((index) => (_jsx(Skeleton, { className: "size-9 rounded-md" }, index)))
|
|
98
|
-
: visibleApps.map((app) => (_jsx("button", { type: "button", "data-chat-first-app": true, "data-app-id": app.id, className: cn("flex size-9 items-center justify-center rounded-md
|
|
98
|
+
: visibleApps.map((app) => (_jsx("button", { type: "button", "data-chat-first-app": true, "data-app-id": app.id, className: cn("flex size-9 items-center justify-center rounded-md", activeAppId === app.id
|
|
99
99
|
? "bg-sidebar-accent text-sidebar-accent-foreground"
|
|
100
|
-
: "text-sidebar-foreground/70 hover:bg-sidebar-accent hover:text-sidebar-accent-foreground"), onClick: () => onOpenApp(app), "aria-label": copy("openApp", { name: app.name }), title: app.name, children: renderIcon(app) }, app.id))), onOpenAllApps ? (_jsx("button", { type: "button", "data-chat-first-all-apps": true, className: "flex size-9 items-center justify-center rounded-md text-sidebar-foreground/70
|
|
100
|
+
: "text-sidebar-foreground/70 hover:bg-sidebar-accent hover:text-sidebar-accent-foreground"), onClick: () => onOpenApp(app), "aria-label": copy("openApp", { name: app.name }), title: app.name, children: renderIcon(app) }, app.id))), onOpenAllApps ? (_jsx("button", { type: "button", "data-chat-first-all-apps": true, className: "flex size-9 items-center justify-center rounded-md text-sidebar-foreground/70 hover:bg-sidebar-accent hover:text-sidebar-accent-foreground", onClick: onOpenAllApps, "aria-label": copy("allApps"), title: copy("allApps"), children: _jsx(IconApps, { size: 16, "aria-hidden": "true" }) })) : null, error ? (_jsx("span", { className: "size-1.5 rounded-full bg-destructive", title: error, "aria-label": error })) : null] }));
|
|
101
101
|
}
|
|
102
|
-
return (_jsxs("section", { "data-chat-first-apps-rail": true, className: "mt-3 px-2 pb-2 pt-2", "aria-label": copy("workspaceApps"), children: [_jsxs("div", { className: "mb-1 flex items-center gap-1.5 px-1 text-[11px] font-medium text-sidebar-foreground/50", children: [_jsx("span", { children: copy("workspaceApps") }), _jsx("span", { className: "ml-auto", children: createTrigger })] }), loading && apps.length === 0 ? (_jsx("div", { className: "space-y-0.5 px-1", children: [0, 1, 2].map((index) => (_jsx(Skeleton, { className: "h-
|
|
103
|
-
}
|
|
102
|
+
return (_jsxs("section", { "data-chat-first-apps-rail": true, className: "mt-3 px-2 pb-2 pt-2", "aria-label": copy("workspaceApps"), children: [_jsxs("div", { className: "mb-1 flex items-center gap-1.5 px-1 text-[11px] font-medium text-sidebar-foreground/50", children: [_jsx("span", { children: copy("workspaceApps") }), _jsx("span", { className: "ml-auto", children: createTrigger })] }), loading && apps.length === 0 ? (_jsx("div", { className: "space-y-0.5 px-1", children: [0, 1, 2].map((index) => (_jsx(Skeleton, { className: "h-8 w-full rounded-md" }, index))) })) : apps.length === 0 ? (_jsxs("div", { className: "px-1", children: [_jsx("p", { className: "text-xs text-sidebar-foreground/55", children: copy("noWorkspaceApps") }), createAppTrigger ? (createTrigger) : onCreateApp ? (_jsxs("button", { type: "button", className: "mt-1 inline-flex h-6 items-center gap-1.5 rounded-md border border-sidebar-border px-2 text-xs text-sidebar-foreground/75 hover:bg-sidebar-accent hover:text-sidebar-foreground", onClick: onCreateApp, children: [_jsx(IconPlus, { size: 13, "aria-hidden": "true" }), copy("createApp")] })) : (createTrigger)] })) : (_jsx(AppRows, { apps: visibleApps, activeAppId: activeAppId, layout: layout, onDragStart: setDraggedAppId, onDrop: reorderApps, onDragEnd: () => setDraggedAppId(null), onOpenApp: onOpenApp, onTogglePinned: togglePinned, onMove: moveApp, renderIcon: renderIcon, copy: copy })), hasMoreApps || showAllApps ? (_jsxs("button", { type: "button", className: "mt-0.5 flex h-8 w-full items-center gap-2 rounded-md px-2 text-xs text-sidebar-foreground/50 hover:bg-sidebar-accent hover:text-sidebar-foreground", onClick: () => setShowAllApps((value) => !value), children: [showAllApps ? (_jsx(IconChevronUp, { size: 14, "aria-hidden": "true" })) : (_jsx(IconChevronDown, { size: 14, "aria-hidden": "true" })), showAllApps ? copy("showLess") : copy("showMore")] })) : null, onOpenAllApps ? (_jsx("div", { className: "mt-1 border-t border-sidebar-border/60 pt-1", children: _jsxs("button", { type: "button", "data-chat-first-all-apps": true, className: "flex h-8 w-full items-center gap-2 rounded-md px-2 text-xs text-sidebar-foreground/55 hover:bg-sidebar-accent hover:text-sidebar-foreground", onClick: onOpenAllApps, children: [_jsx(IconApps, { size: 14, "aria-hidden": "true" }), _jsx("span", { children: copy("allApps") })] }) })) : null, error ? (_jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsxs("button", { type: "button", className: "mt-1 flex items-center gap-1 px-1 text-[10px] text-destructive/80", onClick: onRetry, "aria-label": error, children: [_jsx("span", { className: "size-1.5 rounded-full bg-destructive" }), onRetry ? copy("retry") : copy("appsLoadError")] }) }), _jsx(TooltipContent, { side: "right", children: error })] })) : null] }));
|
|
103
|
+
});
|
|
@@ -9,4 +9,4 @@ export interface ChatFirstChatHistoryProps extends Omit<ChatHistoryListProps, "i
|
|
|
9
9
|
* host. Hosts still own thread fetching and actions, but row rhythm and the
|
|
10
10
|
* Chats section treatment stay identical.
|
|
11
11
|
*/
|
|
12
|
-
export declare function ChatFirstChatHistory({ items, label, className, ...props }: ChatFirstChatHistoryProps): import("react").JSX.Element;
|
|
12
|
+
export declare function ChatFirstChatHistory({ items, label, className, ...props }: ChatFirstChatHistoryProps): import("react").JSX.Element | null;
|
|
@@ -6,5 +6,7 @@ import { ChatHistoryList, } from "../chat/ChatHistoryList.js";
|
|
|
6
6
|
* Chats section treatment stay identical.
|
|
7
7
|
*/
|
|
8
8
|
export function ChatFirstChatHistory({ items, label = "Chats", className, ...props }) {
|
|
9
|
+
if (items.length === 0)
|
|
10
|
+
return null;
|
|
9
11
|
return (_jsxs("section", { "data-chat-first-chat-history": true, className: ["min-h-0 min-w-0", className].filter(Boolean).join(" "), children: [_jsx("p", { className: "mb-1 px-2 text-[11px] font-medium text-sidebar-foreground/50", children: label }), _jsx(ChatHistoryList, { ...props, items: items, variant: "rail", className: "min-w-0" })] }));
|
|
10
12
|
}
|
|
@@ -2,5 +2,5 @@ import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-run
|
|
|
2
2
|
import { IconClock, IconPlus, IconPlugConnected, IconSearch, } from "@tabler/icons-react";
|
|
3
3
|
import { defaultChatFirstCopy } from "./copy.js";
|
|
4
4
|
export function ChatFirstPrimaryNavigation({ onNewChat, onOpenIntegrations, onOpenScheduled, onSearch, copy = defaultChatFirstCopy, }) {
|
|
5
|
-
return (_jsxs(_Fragment, { children: [onNewChat ? (_jsxs("button", { type: "button", className: "flex h-8 w-full items-center gap-2 rounded-md px-2 text-[13px] font-medium text-sidebar-foreground/80
|
|
5
|
+
return (_jsxs(_Fragment, { children: [onNewChat ? (_jsxs("button", { type: "button", className: "flex h-8 w-full items-center gap-2 rounded-md px-2 text-[13px] font-medium text-sidebar-foreground/80 hover:bg-sidebar-accent hover:text-sidebar-accent-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring", onClick: onNewChat, children: [_jsx(IconPlus, { size: 15, className: "shrink-0", "aria-hidden": "true" }), _jsx("span", { children: copy("newChat") })] })) : null, _jsxs("button", { type: "button", className: "flex h-8 w-full items-center gap-2 rounded-md px-2 text-[13px] font-medium text-sidebar-foreground/80 hover:bg-sidebar-accent hover:text-sidebar-accent-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring", onClick: onOpenIntegrations, children: [_jsx(IconPlugConnected, { size: 15, className: "shrink-0", "aria-hidden": "true" }), _jsx("span", { children: copy("integrations") })] }), _jsxs("button", { type: "button", className: "flex h-8 w-full items-center gap-2 rounded-md px-2 text-[13px] font-medium text-sidebar-foreground/80 hover:bg-sidebar-accent hover:text-sidebar-accent-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring", onClick: onOpenScheduled, children: [_jsx(IconClock, { size: 15, className: "shrink-0", "aria-hidden": "true" }), _jsx("span", { children: copy("scheduled") })] }), onSearch ? (_jsxs("button", { type: "button", className: "flex h-8 w-full items-center gap-2 rounded-md px-2 text-[13px] font-medium text-sidebar-foreground/80 hover:bg-sidebar-accent hover:text-sidebar-accent-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring", onClick: onSearch, children: [_jsx(IconSearch, { size: 15, className: "shrink-0", "aria-hidden": "true" }), _jsx("span", { children: copy("search") })] })) : null] }));
|
|
6
6
|
}
|
|
@@ -9,6 +9,15 @@ import { useChangeVersion } from "../use-change-version.js";
|
|
|
9
9
|
import { usePollLoop } from "../use-poll-loop.js";
|
|
10
10
|
import { cn } from "../utils.js";
|
|
11
11
|
const RUN_CHANGE_SETTLE_MS = 250;
|
|
12
|
+
/**
|
|
13
|
+
* Cadence used while a run still reads as active, even for hosts that opted
|
|
14
|
+
* out of idle polling with `pollMs={0}`. Those hosts only refresh on mount and
|
|
15
|
+
* on a `runs` change event, and a run abandoned mid-flight (budget exhausted,
|
|
16
|
+
* dead worker) emits neither — so the spinner has no path back to a terminal
|
|
17
|
+
* status. Polling only while something looks active keeps the idle cost at
|
|
18
|
+
* zero and still lets the server's stale sweep terminalize the row.
|
|
19
|
+
*/
|
|
20
|
+
const ACTIVE_RUN_POLL_MS = 5000;
|
|
12
21
|
function useRunsTrayState({ pollMs = 3000, limit = 5, hideWhenIdle = true, showRecent, }) {
|
|
13
22
|
const t = useT();
|
|
14
23
|
const [runs, setRuns] = useState([]);
|
|
@@ -39,7 +48,11 @@ function useRunsTrayState({ pollMs = 3000, limit = 5, hideWhenIdle = true, showR
|
|
|
39
48
|
const timeout = window.setTimeout(() => void refresh(), RUN_CHANGE_SETTLE_MS);
|
|
40
49
|
return () => window.clearTimeout(timeout);
|
|
41
50
|
}, [refresh, runsVersion]);
|
|
42
|
-
|
|
51
|
+
const hasActiveRun = runs.some((run) => run.status === "running");
|
|
52
|
+
usePollLoop(refresh, {
|
|
53
|
+
intervalMs: pollMs > 0 ? pollMs : ACTIVE_RUN_POLL_MS,
|
|
54
|
+
enabled: pollMs > 0 || hasActiveRun,
|
|
55
|
+
});
|
|
43
56
|
const dismissRun = useCallback(async (runId) => {
|
|
44
57
|
setRuns((current) => current.filter((run) => run.id !== runId));
|
|
45
58
|
try {
|
|
@@ -145,7 +145,7 @@ export function McpConnectionSuggestion({ text, contextText = "", variant = "com
|
|
|
145
145
|
: t("mcpIntegrations.connect");
|
|
146
146
|
return (_jsxs(_Fragment, { children: [_jsxs("div", { className: variant === "response"
|
|
147
147
|
? "agent-mcp-connection-suggestion agent-mcp-connection-suggestion--response mt-3 flex max-w-[520px] items-center gap-2 rounded-lg border border-primary/20 bg-primary/5 px-3 py-2 text-[12px]"
|
|
148
|
-
: "agent-mcp-connection-suggestion agent-mcp-connection-suggestion--composer mx-auto mb-2 flex w-[min(calc(100%_-_1.5rem),
|
|
148
|
+
: "agent-mcp-connection-suggestion agent-mcp-connection-suggestion--composer mx-auto mb-2 flex w-[min(calc(100%_-_1.5rem),750px)] items-center gap-2 rounded-lg border border-primary/20 bg-primary/5 px-3 py-2 text-[12px]", "data-mcp-connection-suggestion": integration.id, "data-mcp-connection-suggestion-variant": variant, children: [_jsx(McpIntegrationLogo, { name: integration.name, logoUrl: integration.logoUrl, integrationId: integration.id, className: "size-6 rounded-md text-[10px]", imageClassName: "size-5" }), _jsx("span", { className: "min-w-0 flex-1 leading-snug text-foreground", children: t(hasApiFallback(apiFallback)
|
|
149
149
|
? "mcpIntegrations.connectSuggestionWithApiToken"
|
|
150
150
|
: "mcpIntegrations.connectSuggestion", { name: integration.name }) }), _jsxs("button", { type: "button", onClick: () => void connect(), disabled: connecting, "aria-busy": connecting, className: "inline-flex shrink-0 items-center gap-1 rounded-md bg-primary px-2.5 py-1.5 text-[11px] font-medium text-primary-foreground hover:bg-primary/90 disabled:pointer-events-none disabled:opacity-60", children: [connecting && _jsx(IconLoader2, { className: "h-3 w-3 animate-spin" }), !connecting &&
|
|
151
151
|
canStartOAuth(integration) &&
|
|
@@ -153,7 +153,7 @@ export function McpConnectionSuggestion({ text, contextText = "", variant = "com
|
|
|
153
153
|
!canStartOAuth(integration) &&
|
|
154
154
|
!hasApiFallback(apiFallback) && (_jsx(IconArrowUpRight, { className: "h-3 w-3" }))] }), _jsx("button", { type: "button", onClick: () => setDismissedId(integration.id), className: "inline-flex h-6 w-6 shrink-0 items-center justify-center rounded text-muted-foreground hover:bg-background hover:text-foreground", "aria-label": t("mcpIntegrations.dismissSuggestion"), children: _jsx(IconX, { className: "h-3.5 w-3.5" }) })] }), error && (_jsx("div", { className: variant === "response"
|
|
155
155
|
? "agent-mcp-connection-suggestion-error agent-mcp-connection-suggestion-error--response mt-1 max-w-[520px] text-[11px] text-destructive"
|
|
156
|
-
: "agent-mcp-connection-suggestion-error agent-mcp-connection-suggestion-error--composer mx-auto mb-2 w-[min(calc(100%_-_1.5rem),
|
|
156
|
+
: "agent-mcp-connection-suggestion-error agent-mcp-connection-suggestion-error--composer mx-auto mb-2 w-[min(calc(100%_-_1.5rem),750px)] text-[11px] text-destructive", children: error })), _jsx(McpIntegrationDialog, { open: dialogOpen, onOpenChange: (open) => {
|
|
157
157
|
setDialogOpen(open);
|
|
158
158
|
if (!open)
|
|
159
159
|
clearMcpConnectionResume();
|
|
@@ -60,6 +60,8 @@ export interface SettingsTabsPageProps {
|
|
|
60
60
|
defaultTab?: string;
|
|
61
61
|
className?: string;
|
|
62
62
|
navClassName?: string;
|
|
63
|
+
/** Optional content rendered at the top of the settings navigation rail. */
|
|
64
|
+
navHeader?: ReactNode;
|
|
63
65
|
contentClassName?: string;
|
|
64
66
|
/** Whether to render the settings search box. Defaults to true. */
|
|
65
67
|
enableSearch?: boolean;
|
|
@@ -83,5 +85,5 @@ export interface SettingsTabsPageProps {
|
|
|
83
85
|
*/
|
|
84
86
|
onValueChange?: (tabId: string) => void;
|
|
85
87
|
}
|
|
86
|
-
export declare function SettingsTabsPage({ general, account, team, whatsNew, extraTabs, generalLabel, accountLabel, teamLabel, whatsNewLabel, ariaLabel, defaultTab, className, navClassName, contentClassName, enableSearch, searchPlaceholder, searchEntries, generalSearchEntries, value, onValueChange, }: SettingsTabsPageProps): import("react").JSX.Element;
|
|
88
|
+
export declare function SettingsTabsPage({ general, account, team, whatsNew, extraTabs, generalLabel, accountLabel, teamLabel, whatsNewLabel, ariaLabel, defaultTab, className, navClassName, navHeader, contentClassName, enableSearch, searchPlaceholder, searchEntries, generalSearchEntries, value, onValueChange, }: SettingsTabsPageProps): import("react").JSX.Element;
|
|
87
89
|
export {};
|
|
@@ -118,7 +118,7 @@ function isEditableElement(element) {
|
|
|
118
118
|
tagName === "select" ||
|
|
119
119
|
element.isContentEditable);
|
|
120
120
|
}
|
|
121
|
-
export function SettingsTabsPage({ general, account, team, whatsNew, extraTabs = [], generalLabel = "General", accountLabel = "Account", teamLabel = "Team", whatsNewLabel = "What's new", ariaLabel = "Settings sections", defaultTab = "general", className, navClassName, contentClassName, enableSearch = true, searchPlaceholder = "Search settings", searchEntries, generalSearchEntries, value, onValueChange, }) {
|
|
121
|
+
export function SettingsTabsPage({ general, account, team, whatsNew, extraTabs = [], generalLabel = "General", accountLabel = "Account", teamLabel = "Team", whatsNewLabel = "What's new", ariaLabel = "Settings sections", defaultTab = "general", className, navClassName, navHeader, contentClassName, enableSearch = true, searchPlaceholder = "Search settings", searchEntries, generalSearchEntries, value, onValueChange, }) {
|
|
122
122
|
const rootRef = useRef(null);
|
|
123
123
|
const searchInputRef = useRef(null);
|
|
124
124
|
const autoFocusedSearchRef = useRef(false);
|
|
@@ -375,7 +375,7 @@ export function SettingsTabsPage({ general, account, team, whatsNew, extraTabs =
|
|
|
375
375
|
}
|
|
376
376
|
};
|
|
377
377
|
const searching = enableSearch && trimmedQuery.length > 0;
|
|
378
|
-
return (_jsxs("div", { ref: rootRef, className: cn("flex h-full min-h-0 w-full flex-col overflow-hidden bg-background sm:flex-row", className), children: [_jsxs("div", { className: cn("flex shrink-0 flex-col gap-2 bg-background p-2 sm:min-h-0 sm:w-60 sm:overflow-y-auto sm:p-4", navClassName), children: [enableSearch ? (_jsxs("div", { className: "relative sm:mb-2", children: [_jsx(IconSearch, { className: "pointer-events-none absolute start-2.5 top-1/2 size-3.5 -translate-y-1/2 text-muted-foreground" }), _jsx("input", { ref: searchInputRef, type: "search", value: query, onChange: (event) => setQuery(event.target.value), onKeyDown: (event) => {
|
|
378
|
+
return (_jsxs("div", { ref: rootRef, className: cn("flex h-full min-h-0 w-full flex-col overflow-hidden bg-background sm:flex-row", className), children: [_jsxs("div", { className: cn("flex shrink-0 flex-col gap-2 bg-background p-2 sm:min-h-0 sm:w-60 sm:overflow-y-auto sm:p-4", navClassName), children: [navHeader, enableSearch ? (_jsxs("div", { className: "relative sm:mb-2", children: [_jsx(IconSearch, { className: "pointer-events-none absolute start-2.5 top-1/2 size-3.5 -translate-y-1/2 text-muted-foreground" }), _jsx("input", { ref: searchInputRef, type: "search", value: query, onChange: (event) => setQuery(event.target.value), onKeyDown: (event) => {
|
|
379
379
|
if (event.key === "Escape")
|
|
380
380
|
setQuery("");
|
|
381
381
|
if (event.key === "Enter" && results[0]) {
|
|
@@ -188,6 +188,14 @@ export interface SSEStreamOptions {
|
|
|
188
188
|
* the tight foreground 75s/90s windows.
|
|
189
189
|
*/
|
|
190
190
|
durableBackgroundRun?: boolean;
|
|
191
|
+
/**
|
|
192
|
+
* Optional reader-local watchdog override. A background follow reader can
|
|
193
|
+
* use a shorter value because a timeout only detaches that read; the follow
|
|
194
|
+
* loop immediately re-checks the server-owned run state.
|
|
195
|
+
*/
|
|
196
|
+
noProgressTimeoutMs?: number;
|
|
197
|
+
/** Reader-local counterpart to `noProgressTimeoutMs` for action preparation. */
|
|
198
|
+
actionPreparationStallTimeoutMs?: number;
|
|
191
199
|
/**
|
|
192
200
|
* Optional caller-owned preparation watchdog state. Passing the same object
|
|
193
201
|
* across reconnect reads keeps a stuck action preparation from getting a
|
|
@@ -113,15 +113,22 @@ export function sseInFlightWorkDelta(ev) {
|
|
|
113
113
|
*/
|
|
114
114
|
export const SSE_DURABLE_NO_PROGRESS_TIMEOUT_MS = 13 * 60_000;
|
|
115
115
|
export const SSE_DURABLE_ACTION_PREPARATION_STALL_TIMEOUT_MS = 13 * 60_000;
|
|
116
|
+
function sseTimeoutOverrideMs(value) {
|
|
117
|
+
return typeof value === "number" && Number.isFinite(value) && value >= 0
|
|
118
|
+
? value
|
|
119
|
+
: undefined;
|
|
120
|
+
}
|
|
116
121
|
export function sseNoProgressTimeoutMs(options) {
|
|
117
|
-
return options?.
|
|
118
|
-
|
|
119
|
-
|
|
122
|
+
return (sseTimeoutOverrideMs(options?.noProgressTimeoutMs) ??
|
|
123
|
+
(options?.durableBackgroundRun === true
|
|
124
|
+
? SSE_DURABLE_NO_PROGRESS_TIMEOUT_MS
|
|
125
|
+
: SSE_NO_PROGRESS_TIMEOUT_MS));
|
|
120
126
|
}
|
|
121
127
|
function sseActionPreparationStallTimeoutMs(options) {
|
|
122
|
-
return options?.
|
|
123
|
-
|
|
124
|
-
|
|
128
|
+
return (sseTimeoutOverrideMs(options?.actionPreparationStallTimeoutMs) ??
|
|
129
|
+
(options?.durableBackgroundRun === true
|
|
130
|
+
? SSE_DURABLE_ACTION_PREPARATION_STALL_TIMEOUT_MS
|
|
131
|
+
: SSE_ACTION_PREPARATION_STALL_TIMEOUT_MS));
|
|
125
132
|
}
|
|
126
133
|
function activityProgressBytes(ev) {
|
|
127
134
|
return typeof ev.progressBytes === "number" &&
|
|
@@ -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
|
-
error: string;
|
|
30
29
|
ok?: undefined;
|
|
30
|
+
error: string;
|
|
31
31
|
} | {
|
|
32
32
|
error?: undefined;
|
|
33
33
|
ok: boolean;
|
package/dist/deploy/build.d.ts
CHANGED
|
@@ -103,12 +103,9 @@ export declare function isIntegrationDurableDispatchDeployEnabled(): boolean;
|
|
|
103
103
|
export declare const NETLIFY_RECURRING_JOBS_FUNCTION_NAME = "agent-native-recurring-jobs";
|
|
104
104
|
export declare function isRecurringJobsDeployEnabled(): boolean;
|
|
105
105
|
/**
|
|
106
|
-
* Keep-warm is
|
|
107
|
-
*
|
|
108
|
-
*
|
|
109
|
-
* quota-limits) as if it were awake 100% of the time with zero users online. On
|
|
110
|
-
* a free-tier Neon that exhausts the compute quota and the database then
|
|
111
|
-
* hard-blocks every read mid-session — the symptom is a dead app, not a slow one.
|
|
106
|
+
* Keep-warm is opt-in because a once-a-minute wake prevents autosuspend on
|
|
107
|
+
* metered scale-to-zero databases. `AGENT_NATIVE_DISABLE_KEEP_WARM` remains a
|
|
108
|
+
* compatibility kill switch and wins when both flags are set.
|
|
112
109
|
*/
|
|
113
110
|
export declare function isKeepWarmDeployEnabled(): boolean;
|
|
114
111
|
/**
|
|
@@ -138,7 +135,8 @@ export declare function resolveKeepWarmSchedule(): string;
|
|
|
138
135
|
* delayed by tens of minutes, which is longer than a scale-to-zero database's
|
|
139
136
|
* autosuspend window and leaves the next visitor to pay the cold-start cost.
|
|
140
137
|
*
|
|
141
|
-
*
|
|
138
|
+
* The feature is opt-in, the background half has its own kill switch, and the
|
|
139
|
+
* cadence is configurable — see
|
|
142
140
|
* `isKeepWarmDeployEnabled`, `isKeepWarmBackgroundDeployEnabled`, and
|
|
143
141
|
* `resolveKeepWarmSchedule`. The tradeoff this function encodes is next-visitor
|
|
144
142
|
* latency against database awake-time, and only the deployment knows which of
|
package/dist/deploy/build.js
CHANGED
|
@@ -2256,24 +2256,26 @@ export function isIntegrationDurableDispatchDeployEnabled() {
|
|
|
2256
2256
|
}
|
|
2257
2257
|
const NETLIFY_KEEP_WARM_FUNCTION_NAME = "agent-native-keep-warm";
|
|
2258
2258
|
export const NETLIFY_RECURRING_JOBS_FUNCTION_NAME = "agent-native-recurring-jobs";
|
|
2259
|
-
/** Shared
|
|
2260
|
-
function
|
|
2259
|
+
/** Shared parser for truthy build environment flags. */
|
|
2260
|
+
function isTruthyEnv(name) {
|
|
2261
2261
|
const value = process.env[name]?.trim();
|
|
2262
2262
|
return !!value && ["1", "true", "yes", "on"].includes(value.toLowerCase());
|
|
2263
2263
|
}
|
|
2264
|
+
/** Shared shape for the `AGENT_NATIVE_DISABLE_*` build kill switches. */
|
|
2265
|
+
function isDisabledByEnv(name) {
|
|
2266
|
+
return isTruthyEnv(name);
|
|
2267
|
+
}
|
|
2264
2268
|
export function isRecurringJobsDeployEnabled() {
|
|
2265
2269
|
return !isDisabledByEnv("AGENT_NATIVE_DISABLE_RECURRING_JOBS");
|
|
2266
2270
|
}
|
|
2267
2271
|
/**
|
|
2268
|
-
* Keep-warm is
|
|
2269
|
-
*
|
|
2270
|
-
*
|
|
2271
|
-
* quota-limits) as if it were awake 100% of the time with zero users online. On
|
|
2272
|
-
* a free-tier Neon that exhausts the compute quota and the database then
|
|
2273
|
-
* hard-blocks every read mid-session — the symptom is a dead app, not a slow one.
|
|
2272
|
+
* Keep-warm is opt-in because a once-a-minute wake prevents autosuspend on
|
|
2273
|
+
* metered scale-to-zero databases. `AGENT_NATIVE_DISABLE_KEEP_WARM` remains a
|
|
2274
|
+
* compatibility kill switch and wins when both flags are set.
|
|
2274
2275
|
*/
|
|
2275
2276
|
export function isKeepWarmDeployEnabled() {
|
|
2276
|
-
return
|
|
2277
|
+
return (isTruthyEnv("AGENT_NATIVE_ENABLE_KEEP_WARM") &&
|
|
2278
|
+
!isDisabledByEnv("AGENT_NATIVE_DISABLE_KEEP_WARM"));
|
|
2277
2279
|
}
|
|
2278
2280
|
/**
|
|
2279
2281
|
* The background warm is a separate, much more expensive knob than the server
|
|
@@ -2286,7 +2288,8 @@ export function isKeepWarmDeployEnabled() {
|
|
|
2286
2288
|
* while dropping the probe storm.
|
|
2287
2289
|
*/
|
|
2288
2290
|
export function isKeepWarmBackgroundDeployEnabled() {
|
|
2289
|
-
return
|
|
2291
|
+
return (isKeepWarmDeployEnabled() &&
|
|
2292
|
+
!isDisabledByEnv("AGENT_NATIVE_DISABLE_KEEP_WARM_BACKGROUND"));
|
|
2290
2293
|
}
|
|
2291
2294
|
const DEFAULT_KEEP_WARM_SCHEDULE = "* * * * *";
|
|
2292
2295
|
/**
|
|
@@ -2319,7 +2322,8 @@ export function resolveKeepWarmSchedule() {
|
|
|
2319
2322
|
* delayed by tens of minutes, which is longer than a scale-to-zero database's
|
|
2320
2323
|
* autosuspend window and leaves the next visitor to pay the cold-start cost.
|
|
2321
2324
|
*
|
|
2322
|
-
*
|
|
2325
|
+
* The feature is opt-in, the background half has its own kill switch, and the
|
|
2326
|
+
* cadence is configurable — see
|
|
2323
2327
|
* `isKeepWarmDeployEnabled`, `isKeepWarmBackgroundDeployEnabled`, and
|
|
2324
2328
|
* `resolveKeepWarmSchedule`. The tradeoff this function encodes is next-visitor
|
|
2325
2329
|
* latency against database awake-time, and only the deployment knows which of
|
|
@@ -2327,7 +2331,10 @@ export function resolveKeepWarmSchedule() {
|
|
|
2327
2331
|
*/
|
|
2328
2332
|
export function emitSingleTemplateNetlifyKeepWarmFunction(projectCwd) {
|
|
2329
2333
|
if (!isKeepWarmDeployEnabled()) {
|
|
2330
|
-
|
|
2334
|
+
const reason = isDisabledByEnv("AGENT_NATIVE_DISABLE_KEEP_WARM")
|
|
2335
|
+
? "AGENT_NATIVE_DISABLE_KEEP_WARM is set."
|
|
2336
|
+
: "AGENT_NATIVE_ENABLE_KEEP_WARM is not enabled.";
|
|
2337
|
+
console.log(`[build] Keep-warm emit skipped: ${reason} ` +
|
|
2331
2338
|
"The database is free to autosuspend; the next visitor after an idle " +
|
|
2332
2339
|
"period pays its cold start.");
|
|
2333
2340
|
return;
|
|
@@ -434,7 +434,7 @@ const messages = {
|
|
|
434
434
|
newTerminal: "New terminal",
|
|
435
435
|
panelOptions: "Agent panel options",
|
|
436
436
|
collapseSidebar: "Collapse sidebar",
|
|
437
|
-
widenChat: "Widen chat
|
|
437
|
+
widenChat: "Widen chat",
|
|
438
438
|
returnChatToLayout: "Return chat to layout",
|
|
439
439
|
expandSidebar: "Expand sidebar",
|
|
440
440
|
hideChats: "Hide chats",
|
|
@@ -11,14 +11,14 @@
|
|
|
11
11
|
* DELETE /_agent-native/notifications/:id — delete
|
|
12
12
|
*/
|
|
13
13
|
export declare function createNotificationsHandler(): import("h3").EventHandlerWithFetch<import("h3").EventHandlerRequest, Promise<"" | import("./types.js").Notification[] | {
|
|
14
|
-
error?: undefined;
|
|
15
14
|
count: number;
|
|
16
15
|
updated?: undefined;
|
|
16
|
+
error?: undefined;
|
|
17
17
|
ok?: undefined;
|
|
18
18
|
} | {
|
|
19
|
-
error?: undefined;
|
|
20
19
|
count?: undefined;
|
|
21
20
|
updated: number;
|
|
21
|
+
error?: undefined;
|
|
22
22
|
ok?: undefined;
|
|
23
23
|
} | {
|
|
24
24
|
count?: undefined;
|
|
@@ -26,8 +26,8 @@ export declare function createNotificationsHandler(): import("h3").EventHandlerW
|
|
|
26
26
|
error: string;
|
|
27
27
|
ok?: undefined;
|
|
28
28
|
} | {
|
|
29
|
-
error?: undefined;
|
|
30
29
|
count?: undefined;
|
|
31
30
|
updated?: undefined;
|
|
31
|
+
error?: undefined;
|
|
32
32
|
ok: boolean;
|
|
33
33
|
}>>;
|
|
@@ -41,27 +41,27 @@ export declare function createObservabilityHandler(): import("h3").EventHandlerW
|
|
|
41
41
|
thumbsUpRate: number;
|
|
42
42
|
avgEvalScore: number;
|
|
43
43
|
} | {
|
|
44
|
-
ok?: undefined;
|
|
45
|
-
error?: undefined;
|
|
46
44
|
summary: import("./types.js").TraceSummary;
|
|
47
45
|
spans: import("./types.js").TraceSpan[];
|
|
48
46
|
id?: undefined;
|
|
49
|
-
} | {
|
|
50
|
-
ok?: undefined;
|
|
51
47
|
error?: undefined;
|
|
48
|
+
ok?: undefined;
|
|
49
|
+
} | {
|
|
52
50
|
summary?: undefined;
|
|
53
51
|
spans?: undefined;
|
|
54
52
|
id: string;
|
|
55
|
-
|
|
53
|
+
error?: undefined;
|
|
56
54
|
ok?: undefined;
|
|
55
|
+
} | {
|
|
57
56
|
summary?: undefined;
|
|
58
57
|
spans?: undefined;
|
|
59
58
|
id?: undefined;
|
|
60
59
|
error: any;
|
|
60
|
+
ok?: undefined;
|
|
61
61
|
} | {
|
|
62
|
-
error?: undefined;
|
|
63
62
|
summary?: undefined;
|
|
64
63
|
spans?: undefined;
|
|
65
64
|
id?: undefined;
|
|
65
|
+
error?: undefined;
|
|
66
66
|
ok: boolean;
|
|
67
67
|
}>>;
|