mirror of
https://github.com/simstudioai/sim.git
synced 2026-01-09 23:17:59 -05:00
Checkpoint
This commit is contained in:
@@ -1,58 +1,37 @@
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
import { z } from 'zod'
|
||||
import { searchDocumentation } from '@/lib/copilot/service'
|
||||
import { NextRequest, NextResponse } from 'next/server'
|
||||
import { createLogger } from '@/lib/logs/console-logger'
|
||||
import { searchDocumentation } from '@/lib/copilot/service'
|
||||
|
||||
const logger = createLogger('DocsSearchAPI')
|
||||
|
||||
const SearchSchema = z.object({
|
||||
query: z.string().min(1, 'Query is required'),
|
||||
topK: z.number().min(1).max(20).default(5),
|
||||
})
|
||||
|
||||
/**
|
||||
* POST /api/docs/search
|
||||
* Search documentation for copilot tools
|
||||
*/
|
||||
export async function POST(req: NextRequest) {
|
||||
const requestId = crypto.randomUUID()
|
||||
|
||||
export async function POST(request: NextRequest) {
|
||||
try {
|
||||
const body = await req.json()
|
||||
const { query, topK } = SearchSchema.parse(body)
|
||||
const { query, topK = 5 } = await request.json()
|
||||
|
||||
logger.info(`[${requestId}] Documentation search request: "${query}"`, { topK })
|
||||
if (!query) {
|
||||
return NextResponse.json({ error: 'Query is required' }, { status: 400 })
|
||||
}
|
||||
|
||||
logger.info('Executing documentation search', { query, topK })
|
||||
|
||||
const results = await searchDocumentation(query, { topK })
|
||||
|
||||
logger.info(`[${requestId}] Found ${results.length} documentation results`, { query })
|
||||
logger.info(`Found ${results.length} documentation results`, { query })
|
||||
|
||||
return NextResponse.json({
|
||||
success: true,
|
||||
results,
|
||||
query,
|
||||
totalResults: results.length,
|
||||
metadata: {
|
||||
requestId,
|
||||
query,
|
||||
topK,
|
||||
},
|
||||
})
|
||||
} catch (error) {
|
||||
if (error instanceof z.ZodError) {
|
||||
return NextResponse.json(
|
||||
{ error: 'Invalid request data', details: error.errors },
|
||||
{ status: 400 }
|
||||
)
|
||||
}
|
||||
|
||||
logger.error(`[${requestId}] Documentation search error:`, error)
|
||||
logger.error('Documentation search API failed', error)
|
||||
return NextResponse.json(
|
||||
{
|
||||
error: 'Failed to search documentation',
|
||||
details: error instanceof Error ? error.message : 'Unknown error',
|
||||
success: false,
|
||||
error: `Documentation search failed: ${error instanceof Error ? error.message : 'Unknown error'}`,
|
||||
},
|
||||
{ status: 500 }
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
56
apps/sim/app/api/workflows/current/yaml/route.ts
Normal file
56
apps/sim/app/api/workflows/current/yaml/route.ts
Normal file
@@ -0,0 +1,56 @@
|
||||
import { NextRequest, NextResponse } from 'next/server'
|
||||
import { createLogger } from '@/lib/logs/console-logger'
|
||||
import { useWorkflowYamlStore } from '@/stores/workflows/yaml/store'
|
||||
|
||||
const logger = createLogger('GetWorkflowYamlAPI')
|
||||
|
||||
export async function POST(request: NextRequest) {
|
||||
try {
|
||||
const { includeMetadata = false } = await request.json()
|
||||
|
||||
logger.info('Executing get user workflow', { includeMetadata })
|
||||
|
||||
// Get the workflow YAML using the same store as the UI
|
||||
const yamlStore = useWorkflowYamlStore.getState()
|
||||
const yamlContent = yamlStore.getYaml()
|
||||
|
||||
if (!yamlContent) {
|
||||
return NextResponse.json(
|
||||
{ success: false, error: 'No workflow content available' },
|
||||
{ status: 404 }
|
||||
)
|
||||
}
|
||||
|
||||
let metadata = undefined
|
||||
if (includeMetadata) {
|
||||
// Get additional workflow metadata if requested
|
||||
const workflowStore = yamlStore as any // Access internal state
|
||||
metadata = {
|
||||
name: workflowStore.workflow?.name || 'Unnamed Workflow',
|
||||
description: workflowStore.workflow?.description || '',
|
||||
createdAt: workflowStore.workflow?.createdAt,
|
||||
updatedAt: workflowStore.workflow?.updatedAt,
|
||||
}
|
||||
}
|
||||
|
||||
logger.info('Successfully generated workflow YAML', {
|
||||
includeMetadata,
|
||||
yamlLength: yamlContent.length
|
||||
})
|
||||
|
||||
return NextResponse.json({
|
||||
success: true,
|
||||
yaml: yamlContent,
|
||||
metadata: metadata,
|
||||
})
|
||||
} catch (error) {
|
||||
logger.error('Get user workflow API failed', error)
|
||||
return NextResponse.json(
|
||||
{
|
||||
success: false,
|
||||
error: `Failed to get user workflow: ${error instanceof Error ? error.message : 'Unknown error'}`,
|
||||
},
|
||||
{ status: 500 }
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -406,7 +406,7 @@ export async function generateChatResponse(
|
||||
content: message,
|
||||
})
|
||||
|
||||
// Define the documentation search tool for the LLM
|
||||
// Define the tools available to the LLM
|
||||
const tools: ProviderToolConfig[] = [
|
||||
{
|
||||
id: 'docs_search_internal',
|
||||
@@ -430,6 +430,24 @@ export async function generateChatResponse(
|
||||
required: ['query'],
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'get_user_workflow',
|
||||
name: 'Get User Workflow',
|
||||
description:
|
||||
'Get the current user workflow as YAML format. This shows all blocks, their configurations, inputs, and connections in the workflow.',
|
||||
params: {},
|
||||
parameters: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
includeMetadata: {
|
||||
type: 'boolean',
|
||||
description: 'Whether to include additional metadata about the workflow (default: false)',
|
||||
default: false,
|
||||
},
|
||||
},
|
||||
required: [],
|
||||
},
|
||||
},
|
||||
]
|
||||
|
||||
const response = await executeProviderRequest(provider, {
|
||||
|
||||
@@ -72,9 +72,77 @@ const docsSearchTool: CopilotTool = {
|
||||
},
|
||||
}
|
||||
|
||||
// Get user workflow as YAML tool for copilot
|
||||
const getUserWorkflowTool: CopilotTool = {
|
||||
id: 'get_user_workflow',
|
||||
name: 'Get User Workflow',
|
||||
description:
|
||||
'Get the current user workflow as YAML format. This shows all blocks, their configurations, inputs, and connections in the workflow.',
|
||||
parameters: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
includeMetadata: {
|
||||
type: 'boolean',
|
||||
description: 'Whether to include additional metadata about the workflow (default: false)',
|
||||
default: false,
|
||||
},
|
||||
},
|
||||
required: [],
|
||||
},
|
||||
execute: async (args: Record<string, any>): Promise<CopilotToolResult> => {
|
||||
try {
|
||||
const { includeMetadata = false } = args
|
||||
|
||||
logger.info('Executing get user workflow', { includeMetadata })
|
||||
|
||||
// Import the workflow YAML store dynamically to avoid import issues
|
||||
const { useWorkflowYamlStore } = await import('@/stores/workflows/yaml/store')
|
||||
const { useWorkflowRegistry } = await import('@/stores/workflows/registry/store')
|
||||
|
||||
// Get the current workflow YAML
|
||||
const yamlContent = useWorkflowYamlStore.getState().getYaml()
|
||||
|
||||
// Get additional metadata if requested
|
||||
let metadata = {}
|
||||
if (includeMetadata) {
|
||||
const registry = useWorkflowRegistry.getState()
|
||||
const activeWorkflowId = registry.activeWorkflowId
|
||||
const activeWorkflow = activeWorkflowId ? registry.workflows[activeWorkflowId] : null
|
||||
|
||||
if (activeWorkflow) {
|
||||
metadata = {
|
||||
workflowId: activeWorkflowId,
|
||||
name: activeWorkflow.name,
|
||||
description: activeWorkflow.description,
|
||||
lastModified: activeWorkflow.lastModified,
|
||||
workspaceId: activeWorkflow.workspaceId,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
logger.info('Successfully retrieved user workflow YAML')
|
||||
|
||||
return {
|
||||
success: true,
|
||||
data: {
|
||||
yaml: yamlContent,
|
||||
metadata: includeMetadata ? metadata : undefined,
|
||||
},
|
||||
}
|
||||
} catch (error) {
|
||||
logger.error('Get user workflow failed', error)
|
||||
return {
|
||||
success: false,
|
||||
error: `Failed to get user workflow: ${error instanceof Error ? error.message : 'Unknown error'}`,
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
// Copilot tools registry
|
||||
const copilotTools: Record<string, CopilotTool> = {
|
||||
docs_search_internal: docsSearchTool,
|
||||
get_user_workflow: getUserWorkflowTool,
|
||||
}
|
||||
|
||||
// Get a copilot tool by ID
|
||||
|
||||
@@ -1,23 +1,6 @@
|
||||
import type { ToolConfig } from '../types'
|
||||
|
||||
export interface DocsSearchParams {
|
||||
query: string
|
||||
topK?: number
|
||||
}
|
||||
|
||||
export interface DocsSearchResponse {
|
||||
results: Array<{
|
||||
id: number
|
||||
title: string
|
||||
url: string
|
||||
content: string
|
||||
similarity: number
|
||||
}>
|
||||
query: string
|
||||
totalResults: number
|
||||
}
|
||||
|
||||
export const docsSearchTool: ToolConfig<DocsSearchParams, DocsSearchResponse> = {
|
||||
export const docsSearchTool: ToolConfig = {
|
||||
id: 'docs_search_internal',
|
||||
name: 'Search Documentation',
|
||||
description:
|
||||
@@ -34,7 +17,6 @@ export const docsSearchTool: ToolConfig<DocsSearchParams, DocsSearchResponse> =
|
||||
type: 'number',
|
||||
required: false,
|
||||
description: 'Number of results to return (default: 5, max: 10)',
|
||||
default: 5,
|
||||
},
|
||||
},
|
||||
|
||||
@@ -50,25 +32,4 @@ export const docsSearchTool: ToolConfig<DocsSearchParams, DocsSearchResponse> =
|
||||
}),
|
||||
isInternalRoute: true,
|
||||
},
|
||||
|
||||
transformResponse: async (response: Response): Promise<any> => {
|
||||
const data = await response.json()
|
||||
|
||||
if (!response.ok) {
|
||||
return {
|
||||
success: false,
|
||||
output: {},
|
||||
error: data.error || 'Failed to search documentation',
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
results: data.results || [],
|
||||
query: data.query || '',
|
||||
totalResults: data.totalResults || 0,
|
||||
},
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
@@ -4,10 +4,17 @@ import { useCustomToolsStore } from '@/stores/custom-tools/store'
|
||||
import { useEnvironmentStore } from '@/stores/settings/environment/store'
|
||||
import { docsSearchTool } from './docs/search'
|
||||
import { tools } from './registry'
|
||||
import { getUserWorkflowTool } from './workflow/get-yaml'
|
||||
import type { TableRow, ToolConfig, ToolResponse } from './types'
|
||||
|
||||
const logger = createLogger('ToolsUtils')
|
||||
|
||||
// Internal-only tools (not exposed to users in workflows)
|
||||
const internalTools: Record<string, ToolConfig> = {
|
||||
docs_search_internal: docsSearchTool,
|
||||
get_user_workflow: getUserWorkflowTool,
|
||||
}
|
||||
|
||||
/**
|
||||
* Transforms a table from the store format to a key-value object
|
||||
* @param table Array of table rows from the store
|
||||
@@ -268,11 +275,6 @@ export function createCustomToolRequestBody(
|
||||
}
|
||||
}
|
||||
|
||||
// Internal-only tools (not exposed to users in workflows)
|
||||
const internalTools: Record<string, ToolConfig> = {
|
||||
docs_search_internal: docsSearchTool,
|
||||
}
|
||||
|
||||
// Get a tool by its ID
|
||||
export function getTool(toolId: string): ToolConfig | undefined {
|
||||
// Check for internal tools first
|
||||
|
||||
29
apps/sim/tools/workflow/get-yaml.ts
Normal file
29
apps/sim/tools/workflow/get-yaml.ts
Normal file
@@ -0,0 +1,29 @@
|
||||
import type { ToolConfig } from '../types'
|
||||
|
||||
export const getUserWorkflowTool: ToolConfig = {
|
||||
id: 'get_user_workflow',
|
||||
name: 'Get User Workflow',
|
||||
description:
|
||||
'Get the current user workflow as YAML format. This shows all blocks, their configurations, inputs, and connections in the workflow.',
|
||||
version: '1.0.0',
|
||||
|
||||
params: {
|
||||
includeMetadata: {
|
||||
type: 'boolean',
|
||||
required: false,
|
||||
description: 'Whether to include additional metadata about the workflow (default: false)',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: '/api/workflows/current/yaml',
|
||||
method: 'POST',
|
||||
headers: () => ({
|
||||
'Content-Type': 'application/json',
|
||||
}),
|
||||
body: (params) => ({
|
||||
includeMetadata: params.includeMetadata || false,
|
||||
}),
|
||||
isInternalRoute: true,
|
||||
},
|
||||
}
|
||||
Reference in New Issue
Block a user