mirror of https://github.com/buster-so/buster.git
Merge branch 'staging' into cursor/replace-select-with-dropdown-component-39ce
This commit is contained in:
commit
90801c89c4
|
@ -1,23 +1,23 @@
|
|||
{
|
||||
"folders": [
|
||||
{ "path": "./apps/api" },
|
||||
{ "path": "./apps/electric-server" },
|
||||
{ "path": "./apps/server" },
|
||||
{ "path": "./apps/trigger" },
|
||||
{ "path": "./apps/web" },
|
||||
{ "path": "./packages/access-controls" },
|
||||
{ "path": "./packages/ai" },
|
||||
{ "path": "./packages/data-source" },
|
||||
{ "path": "./packages/database" },
|
||||
{ "path": "./packages/rerank" },
|
||||
{ "path": "./packages/server-shared" },
|
||||
{ "path": "./packages/slack" },
|
||||
{ "path": "./packages/stored-values" },
|
||||
{ "path": "./packages/supabase" },
|
||||
{ "path": "./packages/test-utils" },
|
||||
{ "path": "./packages/typescript-config" },
|
||||
{ "path": "./packages/vitest-config" },
|
||||
{ "path": "./packages/web-tools" }
|
||||
{ "path": "../apps/api" },
|
||||
{ "path": "../apps/electric-server" },
|
||||
{ "path": "../apps/server" },
|
||||
{ "path": "../apps/trigger" },
|
||||
{ "path": "../apps/web" },
|
||||
{ "path": "../packages/access-controls" },
|
||||
{ "path": "../packages/ai" },
|
||||
{ "path": "../packages/data-source" },
|
||||
{ "path": "../packages/database" },
|
||||
{ "path": "../packages/rerank" },
|
||||
{ "path": "../packages/server-shared" },
|
||||
{ "path": "../packages/slack" },
|
||||
{ "path": "../packages/stored-values" },
|
||||
{ "path": "../packages/supabase" },
|
||||
{ "path": "../packages/test-utils" },
|
||||
{ "path": "../packages/typescript-config" },
|
||||
{ "path": "../packages/vitest-config" },
|
||||
{ "path": "../packages/web-tools" }
|
||||
],
|
||||
"settings": {
|
||||
"editor.defaultFormatter": "biomejs.biome",
|
||||
|
|
|
@ -9,6 +9,39 @@
|
|||
"typescript.suggest.autoImports": true,
|
||||
"typescript.updateImportsOnFileMove.enabled": "always",
|
||||
|
||||
// CRITICAL: Enable TypeScript build mode for project references
|
||||
"typescript.enablePromptUseWorkspaceTsdk": true,
|
||||
"typescript.tsdk": "node_modules/typescript/lib",
|
||||
"typescript.preferences.preferTypeOnlyAutoImports": true,
|
||||
|
||||
// Force TypeScript to use project references
|
||||
"typescript.tsserver.useSyntaxServer": "never",
|
||||
"typescript.tsserver.experimental.enableProjectDiagnostics": true,
|
||||
|
||||
// MONOREPO CRITICAL: Force real-time checking
|
||||
"typescript.tsserver.watchOptions": {
|
||||
"watchFile": "priorityPollingInterval",
|
||||
"watchDirectory": "dynamicPriorityPolling",
|
||||
"fallbackPolling": "dynamicPriorityPolling",
|
||||
"synchronousWatchDirectory": true,
|
||||
"excludeDirectories": ["**/node_modules", "**/target", "**/.turbo"],
|
||||
"excludeFiles": []
|
||||
},
|
||||
|
||||
// Enable automatic TypeScript build
|
||||
"typescript.tsc.autoDetect": "on",
|
||||
|
||||
// Force TypeScript to track all project references
|
||||
"typescript.tsserver.includeCompletionsForModuleExports": true,
|
||||
"typescript.tsserver.includePackageJsonAutoImports": "on",
|
||||
// CRITICAL: Disable syntax-only mode to get full type checking
|
||||
|
||||
// Increase memory for large monorepo
|
||||
"typescript.tsserver.maxTsServerMemory": 16384,
|
||||
|
||||
// Force restart on config changes
|
||||
"typescript.tsserver.restartOnConfigChange": true,
|
||||
|
||||
// Ensure dist folders are NEVER excluded from file watching
|
||||
"files.watcherExclude": {
|
||||
"**/node_modules/**": true,
|
||||
|
@ -16,6 +49,7 @@
|
|||
"**/.git/subtree-cache/**": true,
|
||||
"**/target/**": true,
|
||||
"**/.turbo/**": true
|
||||
// NOTE: We explicitly DO NOT exclude dist folders from watching
|
||||
},
|
||||
|
||||
// Exclude dist folders from file explorer (but keep them in watcher)
|
||||
|
@ -47,8 +81,7 @@
|
|||
"typescript.format.enable": true,
|
||||
"typescript.check.npmIsInstalled": false,
|
||||
"typescript.disableAutomaticTypeAcquisition": true,
|
||||
|
||||
|
||||
|
||||
// Default Biome formatting for all file types
|
||||
"[typescript]": {
|
||||
"editor.defaultFormatter": "biomejs.biome"
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import type { Currency } from '@buster/server-shared/currency';
|
||||
import type { Currency, CurrencyResponse } from '@buster/server-shared/currency';
|
||||
import { Hono } from 'hono';
|
||||
import { requireAuth } from '../../../middleware/auth';
|
||||
import { CURRENCIES_MAP } from './config';
|
||||
|
@ -6,7 +6,7 @@ import { CURRENCIES_MAP } from './config';
|
|||
const app = new Hono();
|
||||
|
||||
app.use('*', requireAuth).get('/', async (c) => {
|
||||
return c.json<Currency[]>(CURRENCIES_MAP);
|
||||
return c.json<CurrencyResponse>(CURRENCIES_MAP);
|
||||
});
|
||||
|
||||
export default app;
|
||||
|
|
|
@ -7,6 +7,8 @@ declare global {
|
|||
ENVIRONMENT: string;
|
||||
NODE_ENV?: 'development' | 'production' | 'test';
|
||||
BUSTER_URL: string;
|
||||
BUSTER_ALERT_CHANNEL_TOKEN?: string;
|
||||
BUSTER_ALERT_CHANNEL_ID?: string;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -211,6 +211,24 @@ export async function sendSlackNotification(
|
|||
slackMessage
|
||||
);
|
||||
|
||||
const busterChannelToken = process.env.BUSTER_ALERT_CHANNEL_TOKEN;
|
||||
const busterChannelId = process.env.BUSTER_ALERT_CHANNEL_ID;
|
||||
|
||||
//Step 6: Send Alert To Buster Channel
|
||||
if (busterChannelToken && busterChannelId) {
|
||||
const busterResult = await sendSlackMessage(
|
||||
busterChannelToken,
|
||||
busterChannelId,
|
||||
slackMessage
|
||||
);
|
||||
if (!busterResult.success) {
|
||||
logger.warn('Failed to send alert to Buster channel', {
|
||||
error: busterResult.error,
|
||||
channelId: busterChannelId,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (result.success) {
|
||||
logger.log('Successfully sent Slack notification', {
|
||||
organizationId: params.organizationId,
|
||||
|
|
|
@ -4,7 +4,7 @@ import { useShape, useShapeStream } from '../instances';
|
|||
import { useChatUpdate } from '@/context/Chats/useChatUpdate';
|
||||
import { updateMessageShapeToIChatMessage } from './helpers';
|
||||
import { useMemoizedFn } from '@/hooks';
|
||||
import { useGetChatMemoized } from '@/api/buster_rest/chats';
|
||||
import { prefetchGetListChats, useGetChatMemoized } from '@/api/buster_rest/chats';
|
||||
import uniq from 'lodash/uniq';
|
||||
|
||||
export const useGetMessage = ({ chatId, messageId }: { chatId: string; messageId: string }) => {
|
||||
|
@ -33,6 +33,7 @@ export const useTrackAndUpdateMessageChanges = (
|
|||
) => {
|
||||
const { onUpdateChatMessage, onUpdateChat } = useChatUpdate();
|
||||
const getChatMemoized = useGetChatMemoized();
|
||||
|
||||
const shape = useMemo(
|
||||
() => messageShape({ chatId: chatId || '', messageId }),
|
||||
[chatId, messageId]
|
||||
|
@ -58,6 +59,10 @@ export const useTrackAndUpdateMessageChanges = (
|
|||
message_ids: allMessageIds
|
||||
});
|
||||
}
|
||||
|
||||
if (iChatMessage.is_completed) {
|
||||
prefetchGetListChats()
|
||||
}
|
||||
}
|
||||
callback?.(iChatMessage);
|
||||
onUpdateChatMessage(iChatMessage);
|
||||
|
|
|
@ -38,7 +38,7 @@ export const useGetListChats = (
|
|||
filters?: Omit<Parameters<typeof getListChats>[0], 'page_token' | 'page_size'>
|
||||
) => {
|
||||
const filtersCompiled: Parameters<typeof getListChats>[0] = useMemo(
|
||||
() => ({ admin_view: false, page_token: 0, page_size: 3500, ...filters }),
|
||||
() => ({ admin_view: false, page_token: 0, page_size: 5000, ...filters }),
|
||||
[filters]
|
||||
);
|
||||
|
||||
|
|
|
@ -6,5 +6,5 @@ export const createNewChat = async (props: ChatCreateRequest) => {
|
|||
};
|
||||
|
||||
export const stopChat = async ({ chatId }: { chatId: string }) => {
|
||||
return mainApiV2.patch<unknown>(`/chats/${chatId}`, { stop: true }).then((res) => res.data);
|
||||
return mainApiV2.delete<unknown>(`/chats/${chatId}/cancel`).then((res) => res.data);
|
||||
};
|
||||
|
|
|
@ -29,7 +29,7 @@ const chatsGetList = (
|
|||
filters?: Omit<Parameters<typeof getListChats>[0], 'page_token' | 'page_size'>
|
||||
) =>
|
||||
queryOptions<ChatListItem[]>({
|
||||
queryKey: ['chats', 'list', filters || { page_token: 0, page_size: 3500 }] as const,
|
||||
queryKey: ['chats', 'list', filters || { page_token: 0, page_size: 5000, admin_view: false }] as const,
|
||||
staleTime: 60 * 1000, // 1 minute
|
||||
initialData: [],
|
||||
initialDataUpdatedAt: 0
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import { queryOptions } from '@tanstack/react-query';
|
||||
import { CurrencyResponse } from '@buster/server-shared/currency';
|
||||
|
||||
export const getCurrencies = queryOptions<{ code: string; description: string; flag: string }[]>({
|
||||
export const getCurrencies = queryOptions<CurrencyResponse>({
|
||||
queryKey: ['nextjs', 'list', 'currencies'],
|
||||
initialData: [],
|
||||
initialDataUpdatedAt: 0,
|
||||
|
|
|
@ -108,29 +108,25 @@ const SubmitButton: React.FC<{
|
|||
onSubmitPreflight: () => void;
|
||||
onStop?: () => void;
|
||||
}> = React.memo(({ disabled, sendIcon, loading, loadingIcon, onSubmitPreflight, onStop }) => {
|
||||
const memoizedPrefix = useMemo(() => {
|
||||
return (
|
||||
const prefix = (
|
||||
<div
|
||||
className={cn('relative h-4 w-4 transition-all duration-300 ease-out will-change-transform')}>
|
||||
<div
|
||||
className={cn(
|
||||
'relative h-4 w-4 transition-all duration-300 ease-out will-change-transform'
|
||||
)}>
|
||||
<div
|
||||
className={`absolute inset-0 transition-all duration-300 ease-out ${loading ? 'scale-80 opacity-0' : 'scale-100 opacity-100'}`}>
|
||||
{sendIcon}
|
||||
</div>
|
||||
<div
|
||||
className={`absolute inset-0 flex items-center justify-center text-sm transition-all duration-300 ease-out ${loading ? 'scale-100 opacity-100' : 'scale-85 opacity-0'}`}>
|
||||
{loadingIcon}
|
||||
</div>
|
||||
className={`absolute inset-0 transition-all duration-300 ease-out ${loading ? 'scale-80 opacity-0' : 'scale-100 opacity-100'}`}>
|
||||
{sendIcon}
|
||||
</div>
|
||||
);
|
||||
}, [loading, sendIcon, loadingIcon]);
|
||||
<div
|
||||
className={`absolute inset-0 flex items-center justify-center text-sm transition-all duration-300 ease-out ${loading ? 'scale-100 opacity-100' : 'scale-85 opacity-0'}`}>
|
||||
{loadingIcon}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
return (
|
||||
<Button
|
||||
rounding={'large'}
|
||||
variant="black"
|
||||
prefix={memoizedPrefix}
|
||||
prefix={prefix}
|
||||
onClick={loading && onStop ? onStop : onSubmitPreflight}
|
||||
disabled={disabled}
|
||||
className={cn(
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import React, { type ChangeEvent, useMemo, useRef, useState } from 'react';
|
||||
import React, { type ChangeEvent, useEffect, useMemo, useRef, useState } from 'react';
|
||||
import { InputTextAreaButton } from '@/components/ui/inputs/InputTextAreaButton';
|
||||
import { useMemoizedFn } from '@/hooks';
|
||||
import { cn } from '@/lib/classMerge';
|
||||
|
@ -17,8 +17,8 @@ export const ChatInput: React.FC = React.memo(() => {
|
|||
const [inputValue, setInputValue] = useState('');
|
||||
|
||||
const disableSubmit = useMemo(() => {
|
||||
return !inputHasText(inputValue);
|
||||
}, [inputValue]);
|
||||
return !inputHasText(inputValue) && !isStreamingMessage;
|
||||
}, [inputValue, isStreamingMessage]);
|
||||
|
||||
const { onSubmitPreflight, onStopChat } = useChatInputFlow({
|
||||
disableSubmit,
|
||||
|
@ -32,6 +32,14 @@ export const ChatInput: React.FC = React.memo(() => {
|
|||
setInputValue(e.target.value);
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
if (hasChat) {
|
||||
requestAnimationFrame(() => {
|
||||
textAreaRef.current?.focus();
|
||||
});
|
||||
}
|
||||
}, [hasChat, textAreaRef]);
|
||||
|
||||
return (
|
||||
<div
|
||||
className={cn(
|
||||
|
|
|
@ -135,8 +135,10 @@ export const useChatInputFlow = ({
|
|||
const onStopChat = useMemoizedFn(() => {
|
||||
if (!chatId) return;
|
||||
onStopChatContext({ chatId, messageId: currentMessageId });
|
||||
textAreaRef.current?.focus();
|
||||
textAreaRef.current?.select();
|
||||
setTimeout(() => {
|
||||
textAreaRef.current?.focus();
|
||||
textAreaRef.current?.select();
|
||||
}, 100);
|
||||
});
|
||||
|
||||
return useMemo(
|
||||
|
|
|
@ -1 +1,2 @@
|
|||
export * from './currency.types';
|
||||
export * from './responses';
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
import { z } from 'zod';
|
||||
import { CurrencySchema } from './currency.types';
|
||||
|
||||
export const CurrencyResponseSchema = z.array(CurrencySchema);
|
||||
|
||||
export type CurrencyResponse = z.infer<typeof CurrencyResponseSchema>;
|
|
@ -0,0 +1,29 @@
|
|||
{
|
||||
"files": [],
|
||||
"references": [
|
||||
// Packages - Base configs first
|
||||
{ "path": "./packages/typescript-config" },
|
||||
{ "path": "./packages/vitest-config" },
|
||||
|
||||
// Core packages
|
||||
{ "path": "./packages/database" },
|
||||
{ "path": "./packages/supabase" },
|
||||
{ "path": "./packages/server-shared" },
|
||||
|
||||
// Feature packages
|
||||
{ "path": "./packages/access-controls" },
|
||||
{ "path": "./packages/ai" },
|
||||
{ "path": "./packages/data-source" },
|
||||
{ "path": "./packages/rerank" },
|
||||
{ "path": "./packages/slack" },
|
||||
{ "path": "./packages/stored-values" },
|
||||
{ "path": "./packages/test-utils" },
|
||||
{ "path": "./packages/web-tools" },
|
||||
|
||||
// Apps
|
||||
{ "path": "./apps/server" },
|
||||
{ "path": "./apps/trigger" },
|
||||
{ "path": "./apps/web" },
|
||||
{ "path": "./apps/electric-server" }
|
||||
]
|
||||
}
|
Loading…
Reference in New Issue