mirror of https://github.com/buster-so/buster.git
sql tools
This commit is contained in:
parent
82c1ea7f46
commit
71d862e51b
|
@ -76,9 +76,7 @@ const ExecuteSqlOutputSchema = z.object({
|
|||
export type ExecuteSqlOutput = z.infer<typeof ExecuteSqlOutputSchema>;
|
||||
|
||||
// Factory function to create the execute-sql tool
|
||||
export function createExecuteSqlTool<TAgentContext extends ExecuteSqlContext = ExecuteSqlContext>(
|
||||
context: TAgentContext
|
||||
) {
|
||||
export function createExecuteSqlTool(context: ExecuteSqlContext) {
|
||||
// Initialize state for streaming
|
||||
const state: ExecuteSqlState = {
|
||||
toolCallId: undefined,
|
||||
|
@ -110,40 +108,3 @@ export function createExecuteSqlTool<TAgentContext extends ExecuteSqlContext = E
|
|||
onInputAvailable,
|
||||
});
|
||||
}
|
||||
|
||||
// Legacy export for backward compatibility
|
||||
export const executeSql = tool({
|
||||
description: `Use this to run lightweight, validation queries to understand values in columns, date ranges, etc.
|
||||
Please limit your queries to 50 rows for performance.
|
||||
Query results will be limited to 50 rows for performance.
|
||||
You must use the <SCHEMA_NAME>.<TABLE_NAME> syntax/qualifier for all table names.
|
||||
Otherwise the queries wont run successfully.`,
|
||||
inputSchema: ExecuteSqlInputSchema,
|
||||
outputSchema: ExecuteSqlOutputSchema,
|
||||
execute: async (input, { experimental_context: context }) => {
|
||||
const rawContext = context as AnalystAgentOptions;
|
||||
|
||||
const executeSqlContext = ExecuteSqlContextSchema.parse({
|
||||
dataSourceId: rawContext.dataSourceId,
|
||||
userId: rawContext.userId,
|
||||
dataSourceSyntax: rawContext.dataSourceSyntax,
|
||||
messageId: rawContext.messageId || '',
|
||||
});
|
||||
|
||||
// Create temporary state for this execution
|
||||
const state: ExecuteSqlState = {
|
||||
toolCallId: undefined,
|
||||
args: JSON.stringify(input),
|
||||
statements: input.statements,
|
||||
isComplete: true,
|
||||
startTime: Date.now(),
|
||||
executionTime: undefined,
|
||||
executionResults: undefined,
|
||||
};
|
||||
|
||||
const executeFunction = createExecuteSqlExecute(state, executeSqlContext);
|
||||
return await executeFunction(input);
|
||||
},
|
||||
});
|
||||
|
||||
export default executeSql;
|
||||
|
|
|
@ -72,9 +72,7 @@ const SuperExecuteSqlOutputSchema = z.object({
|
|||
export type SuperExecuteSqlOutput = z.infer<typeof SuperExecuteSqlOutputSchema>;
|
||||
|
||||
// Factory function to create the super-execute-sql tool
|
||||
export function createSuperExecuteSqlTool<
|
||||
TAgentContext extends SuperExecuteSqlContext = SuperExecuteSqlContext,
|
||||
>(context: TAgentContext) {
|
||||
export function createSuperExecuteSqlTool(context: SuperExecuteSqlContext) {
|
||||
// Initialize state
|
||||
const state: SuperExecuteSqlState = {
|
||||
startTime: Date.now(),
|
||||
|
|
|
@ -21,11 +21,60 @@ import type {
|
|||
CreateDashboardsState,
|
||||
} from './create-dashboards-tool';
|
||||
import {
|
||||
createDashboardsRawLlMessageEntry,
|
||||
createDashboardsReasoningMessage,
|
||||
createDashboardsResponseMessage,
|
||||
createCreateDashboardsRawLlmMessageEntry,
|
||||
createCreateDashboardsReasoningEntry,
|
||||
} from './helpers/create-dashboards-tool-transform-helper';
|
||||
|
||||
// Type definitions
|
||||
interface DashboardFileContent {
|
||||
rows: Array<{
|
||||
items: Array<{
|
||||
id: string;
|
||||
[key: string]: unknown;
|
||||
}>;
|
||||
[key: string]: unknown;
|
||||
}>;
|
||||
[key: string]: unknown;
|
||||
}
|
||||
|
||||
interface FileWithId {
|
||||
id: string;
|
||||
name: string;
|
||||
file_type: string;
|
||||
result_message?: string;
|
||||
results?: Record<string, unknown>[];
|
||||
created_at: string;
|
||||
updated_at: string;
|
||||
version_number: number;
|
||||
content?: DashboardFileContent;
|
||||
}
|
||||
|
||||
interface FailedFileCreation {
|
||||
name: string;
|
||||
error: string;
|
||||
}
|
||||
|
||||
type CreateDashboardFilesParams = CreateDashboardsInput;
|
||||
type CreateDashboardFilesOutput = CreateDashboardsOutput;
|
||||
|
||||
// Dashboard YAML schema
|
||||
const dashboardYmlSchema = z.object({
|
||||
name: z.string().min(1, 'Dashboard name is required'),
|
||||
description: z.string().optional(),
|
||||
rows: z.array(
|
||||
z.object({
|
||||
id: z.string(),
|
||||
items: z.array(
|
||||
z.object({
|
||||
id: z.string(),
|
||||
}).passthrough()
|
||||
),
|
||||
column_sizes: z.array(z.number()).optional(),
|
||||
rowHeight: z.number().optional(),
|
||||
}).passthrough()
|
||||
).min(1, 'Dashboard must have at least one row'),
|
||||
});
|
||||
|
||||
// Parse and validate dashboard YAML content
|
||||
function parseAndValidateYaml(ymlContent: string): {
|
||||
success: boolean;
|
||||
|
@ -96,7 +145,7 @@ async function validateMetricIds(
|
|||
}
|
||||
|
||||
// Process a dashboard file creation request
|
||||
async function processDashboardFile(file: CreateDashboardsInput): Promise<{
|
||||
async function processDashboardFile(file: { name: string; yml_content: string }): Promise<{
|
||||
success: boolean;
|
||||
dashboardFile?: FileWithId;
|
||||
dashboardYml?: DashboardYml;
|
||||
|
@ -445,34 +494,34 @@ export function createCreateDashboardsExecute(
|
|||
const finalStatus = typedResult.failed_files?.length ? 'failed' : 'completed';
|
||||
const toolCallId = state.toolCallId || `tool-${Date.now()}`;
|
||||
|
||||
const reasoningEntry = createDashboardsReasoningMessage(
|
||||
toolCallId,
|
||||
state.files ?? [],
|
||||
finalStatus
|
||||
);
|
||||
const responseEntry = createDashboardsResponseMessage(
|
||||
toolCallId,
|
||||
typedResult.message
|
||||
);
|
||||
const rawLlmMessage: ModelMessage = {
|
||||
role: 'assistant',
|
||||
content: [
|
||||
{
|
||||
type: 'tool-call',
|
||||
toolCallId,
|
||||
toolName: 'create-dashboards',
|
||||
input: state.parsedArgs || (input as Partial<CreateDashboardFilesParams>),
|
||||
},
|
||||
],
|
||||
// Update state for final status
|
||||
if (state.files) {
|
||||
state.files.forEach(f => {
|
||||
if (!f.status || f.status === 'processing') {
|
||||
f.status = finalStatus === 'failed' ? 'failed' : 'completed';
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
const reasoningEntry = createCreateDashboardsReasoningEntry(state, toolCallId);
|
||||
const rawLlmMessage = createCreateDashboardsRawLlmMessageEntry(state, toolCallId);
|
||||
|
||||
const updates: Parameters<typeof updateMessageEntries>[0] = {
|
||||
messageId: context.messageId,
|
||||
mode: 'update',
|
||||
};
|
||||
|
||||
await updateMessageEntries({
|
||||
messageId: context.messageId,
|
||||
reasoningEntry,
|
||||
responseEntry,
|
||||
rawLlmMessage,
|
||||
mode: 'update',
|
||||
});
|
||||
if (reasoningEntry) {
|
||||
updates.responseEntry = reasoningEntry;
|
||||
}
|
||||
|
||||
if (rawLlmMessage) {
|
||||
updates.rawLlmMessageEntry = rawLlmMessage;
|
||||
}
|
||||
|
||||
if (reasoningEntry || rawLlmMessage) {
|
||||
await updateMessageEntries(updates);
|
||||
}
|
||||
|
||||
console.info('[create-dashboards] Updated last entries with final results', {
|
||||
messageId: context.messageId,
|
||||
|
@ -505,29 +554,32 @@ export function createCreateDashboardsExecute(
|
|||
if (context.messageId) {
|
||||
try {
|
||||
const toolCallId = state.toolCallId || `tool-${Date.now()}`;
|
||||
const reasoningEntry = createDashboardsReasoningMessage(
|
||||
toolCallId,
|
||||
(state.files ?? []).map((f) => ({ ...f, status: 'failed' })),
|
||||
'failed'
|
||||
);
|
||||
const rawLlmMessage: ModelMessage = {
|
||||
role: 'assistant',
|
||||
content: [
|
||||
{
|
||||
type: 'tool-call',
|
||||
toolCallId,
|
||||
toolName: 'create-dashboards',
|
||||
input: state.parsedArgs || {},
|
||||
},
|
||||
],
|
||||
// Update state files to failed status
|
||||
if (state.files) {
|
||||
state.files.forEach(f => {
|
||||
f.status = 'failed';
|
||||
});
|
||||
}
|
||||
|
||||
const reasoningEntry = createCreateDashboardsReasoningEntry(state, toolCallId);
|
||||
const rawLlmMessage = createCreateDashboardsRawLlmMessageEntry(state, toolCallId);
|
||||
|
||||
const updates: Parameters<typeof updateMessageEntries>[0] = {
|
||||
messageId: context.messageId,
|
||||
mode: 'update',
|
||||
};
|
||||
|
||||
await updateMessageEntries({
|
||||
messageId: context.messageId,
|
||||
reasoningEntry,
|
||||
rawLlmMessage,
|
||||
mode: 'update',
|
||||
});
|
||||
if (reasoningEntry) {
|
||||
updates.responseEntry = reasoningEntry;
|
||||
}
|
||||
|
||||
if (rawLlmMessage) {
|
||||
updates.rawLlmMessageEntry = rawLlmMessage;
|
||||
}
|
||||
|
||||
if (reasoningEntry || rawLlmMessage) {
|
||||
await updateMessageEntries(updates);
|
||||
}
|
||||
} catch (updateError) {
|
||||
console.error('[create-dashboards] Error updating entries on failure:', updateError);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue