From 4b80fe7a662390f4004e47fe13b9baf73128e29c Mon Sep 17 00:00:00 2001 From: Nate Kelley Date: Fri, 26 Sep 2025 12:11:41 -0600 Subject: [PATCH 1/3] extended refer --- .../features/ShareMenu/ShareMenuContentEmbed.tsx | 14 ++++++++++++++ .../src/components/ui/inputs/InputTextArea.tsx | 15 ++++++++------- .../components/ui/inputs/InputTextAreaButton.tsx | 6 +++--- 3 files changed, 25 insertions(+), 10 deletions(-) diff --git a/apps/web/src/components/features/ShareMenu/ShareMenuContentEmbed.tsx b/apps/web/src/components/features/ShareMenu/ShareMenuContentEmbed.tsx index 604d4de81..356c99924 100644 --- a/apps/web/src/components/features/ShareMenu/ShareMenuContentEmbed.tsx +++ b/apps/web/src/components/features/ShareMenu/ShareMenuContentEmbed.tsx @@ -59,6 +59,20 @@ export const ShareMenuContentEmbedFooter = ({ openSuccessMessage('Succuessfully published'); }; + const text = useMemo(() => { + if (assetType === 'metric_file') { + return 'Your metric currently isn’t published.'; + } else if (assetType === 'dashboard_file') { + return 'Your dashboard currently isn’t published.'; + } else if (assetType === 'chat') { + return 'Your chat currently isn’t published.'; + } else if (assetType === 'report_file') { + return 'Your report currently isn’t published.'; + } else { + return 'Your item currently isn’t published.'; + } + }, [assetType]); + return (
diff --git a/apps/web/src/components/ui/inputs/InputTextArea.tsx b/apps/web/src/components/ui/inputs/InputTextArea.tsx index 146597ec0..a926b494f 100644 --- a/apps/web/src/components/ui/inputs/InputTextArea.tsx +++ b/apps/web/src/components/ui/inputs/InputTextArea.tsx @@ -28,7 +28,7 @@ export interface InputTextAreaProps onPressEnter?: (e: React.KeyboardEvent) => void; } -export interface InputTextAreaRef { +export interface InputTextAreaRef extends HTMLTextAreaElement { forceRecalculateHeight: () => void; } @@ -48,9 +48,11 @@ export const InputTextArea = React.forwardRef { const textareaRef = useRef(null); - useImperativeHandle( - ref, - () => ({ + useImperativeHandle(ref, () => { + if (!textareaRef.current) { + return null as unknown as InputTextAreaRef; + } + return Object.assign(textareaRef.current, { forceRecalculateHeight: () => { if (textareaRef.current) { // Force a recalculation by triggering an input event @@ -58,9 +60,8 @@ export const InputTextArea = React.forwardRef) => { if (e.key === 'Enter') { diff --git a/apps/web/src/components/ui/inputs/InputTextAreaButton.tsx b/apps/web/src/components/ui/inputs/InputTextAreaButton.tsx index e9fca6c76..9df7f2b31 100644 --- a/apps/web/src/components/ui/inputs/InputTextAreaButton.tsx +++ b/apps/web/src/components/ui/inputs/InputTextAreaButton.tsx @@ -4,7 +4,7 @@ import { cn } from '@/lib/classMerge'; import { Button } from '../buttons/Button'; import ShapeSquare from '../icons/NucleoIconFilled/shape-square'; import { ArrowUp } from '../icons/NucleoIconOutlined'; -import { InputTextArea, type InputTextAreaProps } from './InputTextArea'; +import { InputTextArea, type InputTextAreaProps, type InputTextAreaRef } from './InputTextArea'; const inputTextAreaButtonVariants = cva( 'relative flex flex-col w-full items-center overflow-visible rounded-xl cursor-text border border-border transition-all duration-200', @@ -29,7 +29,7 @@ export interface InputTextAreaButtonProps extends Omit( +export const InputTextAreaButton = forwardRef( ( { className, @@ -51,7 +51,7 @@ export const InputTextAreaButton = forwardRef { const onSubmitPreflight = () => { if (disabled) return; - const text = (textRef as React.RefObject).current?.value || ''; + const text = (textRef as React.RefObject).current?.value || ''; onSubmit(text); }; From 0b17429e10c926bcbc81520982a18d523f6b73e4 Mon Sep 17 00:00:00 2001 From: dal Date: Fri, 26 Sep 2025 12:59:48 -0600 Subject: [PATCH 2/3] streaming fix - need to wait for pending updates --- packages/ai/src/agents/analyst-agent/analyst-agent.ts | 5 ++++- .../think-and-prep-agent/think-and-prep-agent.ts | 6 ++++++ .../done-tool/done-tool-execute.ts | 6 +++++- .../src/queries/messages/update-message-entries.ts | 11 +++++++++++ 4 files changed, 26 insertions(+), 2 deletions(-) diff --git a/packages/ai/src/agents/analyst-agent/analyst-agent.ts b/packages/ai/src/agents/analyst-agent/analyst-agent.ts index 23ab7f86a..b79c110cc 100644 --- a/packages/ai/src/agents/analyst-agent/analyst-agent.ts +++ b/packages/ai/src/agents/analyst-agent/analyst-agent.ts @@ -1,4 +1,5 @@ import type { PermissionedDataset } from '@buster/access-controls'; +import { waitForPendingUpdates } from '@buster/database/queries'; import { type ModelMessage, hasToolCall, stepCountIs, streamText } from 'ai'; import { wrapTraced } from 'braintrust'; import z from 'zod'; @@ -199,8 +200,10 @@ export function createAnalystAgent(analystAgentOptions: AnalystAgentOptions) { hasToolResults: !!event.toolResults, }); }, - onFinish: () => { + onFinish: async () => { console.info('Analyst Agent finished'); + // Ensure all pending database updates complete before stream terminates + await waitForPendingUpdates(analystAgentOptions.messageId); }, }), { diff --git a/packages/ai/src/agents/think-and-prep-agent/think-and-prep-agent.ts b/packages/ai/src/agents/think-and-prep-agent/think-and-prep-agent.ts index cdf89bda9..feac20378 100644 --- a/packages/ai/src/agents/think-and-prep-agent/think-and-prep-agent.ts +++ b/packages/ai/src/agents/think-and-prep-agent/think-and-prep-agent.ts @@ -1,4 +1,5 @@ import type { PermissionedDataset } from '@buster/access-controls'; +import { waitForPendingUpdates } from '@buster/database/queries'; import { type ModelMessage, hasToolCall, stepCountIs, streamText } from 'ai'; import { wrapTraced } from 'braintrust'; import z from 'zod'; @@ -230,6 +231,11 @@ export function createThinkAndPrepAgent(thinkAndPrepAgentSchema: ThinkAndPrepAge hasToolResults: !!event.toolResults, }); }, + onFinish: async () => { + console.info('Think and Prep Agent finished'); + // Ensure all pending database updates complete before stream terminates + await waitForPendingUpdates(messageId); + }, }), { name: 'Think and Prep Agent', diff --git a/packages/ai/src/tools/communication-tools/done-tool/done-tool-execute.ts b/packages/ai/src/tools/communication-tools/done-tool/done-tool-execute.ts index 40b2a22b3..b29211d38 100644 --- a/packages/ai/src/tools/communication-tools/done-tool/done-tool-execute.ts +++ b/packages/ai/src/tools/communication-tools/done-tool/done-tool-execute.ts @@ -1,4 +1,4 @@ -import { updateMessage, updateMessageEntries } from '@buster/database/queries'; +import { updateMessage, updateMessageEntries, waitForPendingUpdates } from '@buster/database/queries'; import { wrapTraced } from 'braintrust'; import { cleanupState } from '../../shared/cleanup-state'; import { createRawToolResultEntry } from '../../shared/create-raw-llm-tool-result-entry'; @@ -57,6 +57,10 @@ export function createDoneToolExecute(context: DoneToolContext, state: DoneToolS } const result = await processDone(state, state.toolCallId, context.messageId, context); + + // Wait for all pending updates from delta/finish to complete before returning + await waitForPendingUpdates(context.messageId); + cleanupState(state); return result; }, diff --git a/packages/database/src/queries/messages/update-message-entries.ts b/packages/database/src/queries/messages/update-message-entries.ts index 3b56d6d3c..b7f705360 100644 --- a/packages/database/src/queries/messages/update-message-entries.ts +++ b/packages/database/src/queries/messages/update-message-entries.ts @@ -24,6 +24,17 @@ export type UpdateMessageEntriesParams = z.infer>(); +/** + * Wait for all pending updates for a given messageId to complete. + * This ensures all queued updates are flushed to the database before proceeding. + */ +export async function waitForPendingUpdates(messageId: string): Promise { + const pendingQueue = updateQueues.get(messageId); + if (pendingQueue) { + await pendingQueue; + } +} + /** * Internal function that performs the actual update logic. * This is separated so it can be queued. From ecbe98099c2dc7726373d2f46ec364b0748a4a55 Mon Sep 17 00:00:00 2001 From: dal Date: Fri, 26 Sep 2025 13:01:15 -0600 Subject: [PATCH 3/3] linting updates --- .../communication-tools/done-tool/done-tool-execute.ts | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/packages/ai/src/tools/communication-tools/done-tool/done-tool-execute.ts b/packages/ai/src/tools/communication-tools/done-tool/done-tool-execute.ts index b29211d38..fbd7062b7 100644 --- a/packages/ai/src/tools/communication-tools/done-tool/done-tool-execute.ts +++ b/packages/ai/src/tools/communication-tools/done-tool/done-tool-execute.ts @@ -1,4 +1,8 @@ -import { updateMessage, updateMessageEntries, waitForPendingUpdates } from '@buster/database/queries'; +import { + updateMessage, + updateMessageEntries, + waitForPendingUpdates, +} from '@buster/database/queries'; import { wrapTraced } from 'braintrust'; import { cleanupState } from '../../shared/cleanup-state'; import { createRawToolResultEntry } from '../../shared/create-raw-llm-tool-result-entry'; @@ -57,10 +61,10 @@ export function createDoneToolExecute(context: DoneToolContext, state: DoneToolS } const result = await processDone(state, state.toolCallId, context.messageId, context); - + // Wait for all pending updates from delta/finish to complete before returning await waitForPendingUpdates(context.messageId); - + cleanupState(state); return result; },