mirror of
https://github.com/simstudioai/sim.git
synced 2026-09-24 15:45:35 +08:00
Standardized output format for blocks/tools. Updated executor so we can now resolve sub-json values for tagged inputs. Updated serializer to match new block output format.
This commit is contained in:
+11
-5
@@ -12,8 +12,11 @@ interface ChatParams {
|
||||
}
|
||||
|
||||
interface ChatResponse extends ToolResponse {
|
||||
tokens?: number
|
||||
model: string
|
||||
output: {
|
||||
content: string
|
||||
model: string
|
||||
tokens?: number
|
||||
}
|
||||
}
|
||||
|
||||
export const chatTool: ToolConfig<ChatParams, ChatResponse> = {
|
||||
@@ -81,9 +84,12 @@ export const chatTool: ToolConfig<ChatParams, ChatResponse> = {
|
||||
transformResponse: async (response: Response) => {
|
||||
const data = await response.json()
|
||||
return {
|
||||
output: data.completion,
|
||||
tokens: data.usage?.total_tokens,
|
||||
model: data.model
|
||||
success: true,
|
||||
output: {
|
||||
content: data.completion,
|
||||
model: data.model,
|
||||
tokens: data.usage?.total_tokens
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
+13
-9
@@ -8,9 +8,11 @@ interface VisionParams {
|
||||
}
|
||||
|
||||
interface VisionResponse extends ToolResponse {
|
||||
response: string
|
||||
tokens?: number
|
||||
model?: string
|
||||
output: {
|
||||
content: string
|
||||
model?: string
|
||||
tokens?: number
|
||||
}
|
||||
}
|
||||
|
||||
export const visionTool: ToolConfig<VisionParams, VisionResponse> = {
|
||||
@@ -115,12 +117,14 @@ export const visionTool: ToolConfig<VisionParams, VisionResponse> = {
|
||||
}
|
||||
|
||||
return {
|
||||
output: result,
|
||||
response: result,
|
||||
model: data.model,
|
||||
tokens: data.content
|
||||
? (data.usage?.input_tokens + data.usage?.output_tokens)
|
||||
: data.usage?.total_tokens
|
||||
success: true,
|
||||
output: {
|
||||
content: result,
|
||||
model: data.model,
|
||||
tokens: data.content
|
||||
? (data.usage?.input_tokens + data.usage?.output_tokens)
|
||||
: data.usage?.total_tokens
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
+11
-5
@@ -15,8 +15,11 @@ interface ChatParams {
|
||||
}
|
||||
|
||||
interface ChatResponse extends ToolResponse {
|
||||
tokens?: number
|
||||
model: string
|
||||
output: {
|
||||
content: string
|
||||
model: string
|
||||
tokens?: number
|
||||
}
|
||||
}
|
||||
|
||||
export const chatTool: ToolConfig<ChatParams, ChatResponse> = {
|
||||
@@ -105,9 +108,12 @@ export const chatTool: ToolConfig<ChatParams, ChatResponse> = {
|
||||
|
||||
const data = await response.json()
|
||||
return {
|
||||
output: data.choices[0].message.content,
|
||||
tokens: data.usage?.total_tokens,
|
||||
model: data.model
|
||||
success: true,
|
||||
output: {
|
||||
content: data.choices[0].message.content,
|
||||
model: data.model,
|
||||
tokens: data.usage?.total_tokens
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
@@ -14,9 +14,11 @@ interface ChatParams {
|
||||
}
|
||||
|
||||
interface ChatResponse extends ToolResponse {
|
||||
tokens?: number
|
||||
model: string
|
||||
reasoning_content?: string
|
||||
output: {
|
||||
content: string
|
||||
model: string
|
||||
tokens?: number
|
||||
}
|
||||
}
|
||||
|
||||
export const reasonerTool: ToolConfig<ChatParams, ChatResponse> = {
|
||||
@@ -99,10 +101,12 @@ export const reasonerTool: ToolConfig<ChatParams, ChatResponse> = {
|
||||
|
||||
const data = await response.json()
|
||||
return {
|
||||
output: data.choices[0].message.content,
|
||||
tokens: data.usage?.total_tokens,
|
||||
model: data.model,
|
||||
reasoning_content: data.choices[0].message.reasoning_content
|
||||
success: true,
|
||||
output: {
|
||||
content: data.choices[0].message.content,
|
||||
model: data.model,
|
||||
tokens: data.usage?.total_tokens
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
@@ -10,8 +10,7 @@ interface ScrapeParams {
|
||||
}
|
||||
|
||||
interface ScrapeResponse extends ToolResponse {
|
||||
success: boolean
|
||||
data: {
|
||||
output: {
|
||||
markdown: string
|
||||
html?: string
|
||||
metadata: {
|
||||
@@ -77,9 +76,12 @@ export const scrapeTool: ToolConfig<ScrapeParams, ScrapeResponse> = {
|
||||
}
|
||||
|
||||
return {
|
||||
success: data.success,
|
||||
data: data.data,
|
||||
output: data.data.markdown
|
||||
success: true,
|
||||
output: {
|
||||
markdown: data.data.markdown,
|
||||
html: data.data.html,
|
||||
metadata: data.data.metadata
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
@@ -6,7 +6,10 @@ interface CodeExecutionInput {
|
||||
}
|
||||
|
||||
interface CodeExecutionOutput extends ToolResponse {
|
||||
output: Record<string, any>
|
||||
output: {
|
||||
result: any
|
||||
stdout: string
|
||||
}
|
||||
}
|
||||
|
||||
export const functionExecuteTool: ToolConfig<CodeExecutionInput, CodeExecutionOutput> = {
|
||||
@@ -68,13 +71,21 @@ export const functionExecuteTool: ToolConfig<CodeExecutionInput, CodeExecutionOu
|
||||
try {
|
||||
// Try parsing the output as JSON
|
||||
const parsed = JSON.parse(stdout)
|
||||
return { output: parsed }
|
||||
} catch {
|
||||
// If not JSON, wrap it in a JSON object
|
||||
return {
|
||||
output: {
|
||||
result: stdout
|
||||
}
|
||||
success: true,
|
||||
output: {
|
||||
result: parsed,
|
||||
stdout
|
||||
}
|
||||
}
|
||||
} catch {
|
||||
// If not JSON, return as string
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
result: stdout,
|
||||
stdout
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
+13
-7
@@ -12,9 +12,12 @@ interface ChatParams {
|
||||
}
|
||||
|
||||
interface ChatResponse extends ToolResponse {
|
||||
tokens?: number
|
||||
model: string
|
||||
safetyRatings?: any[]
|
||||
output: {
|
||||
content: string
|
||||
model: string
|
||||
tokens?: number
|
||||
safetyRatings?: any[]
|
||||
}
|
||||
}
|
||||
|
||||
export const chatTool: ToolConfig<ChatParams, ChatResponse> = {
|
||||
@@ -88,10 +91,13 @@ export const chatTool: ToolConfig<ChatParams, ChatResponse> = {
|
||||
transformResponse: async (response: Response) => {
|
||||
const data = await response.json()
|
||||
return {
|
||||
output: data.candidates[0].content.parts[0].text,
|
||||
tokens: data.usage?.totalTokens,
|
||||
model: data.model,
|
||||
safetyRatings: data.candidates[0].safetyRatings
|
||||
success: true,
|
||||
output: {
|
||||
content: data.candidates[0].content.parts[0].text,
|
||||
model: data.model,
|
||||
tokens: data.usage?.totalTokens,
|
||||
safetyRatings: data.candidates[0].safetyRatings
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
+11
-5
@@ -13,8 +13,11 @@ interface RequestParams {
|
||||
}
|
||||
|
||||
interface RequestResponse extends ToolResponse {
|
||||
status: number
|
||||
headers: Record<string, string>
|
||||
output: {
|
||||
data: any
|
||||
status: number
|
||||
headers: Record<string, string>
|
||||
}
|
||||
}
|
||||
|
||||
export const requestTool: ToolConfig<RequestParams, RequestResponse> = {
|
||||
@@ -132,9 +135,12 @@ export const requestTool: ToolConfig<RequestParams, RequestResponse> = {
|
||||
: response.text())
|
||||
|
||||
return {
|
||||
output: data,
|
||||
status: response.status,
|
||||
headers
|
||||
success: response.ok,
|
||||
output: {
|
||||
data,
|
||||
status: response.status,
|
||||
headers
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
@@ -16,11 +16,14 @@ interface ContactsParams {
|
||||
}
|
||||
|
||||
interface ContactsResponse extends ToolResponse {
|
||||
totalResults?: number
|
||||
pagination?: {
|
||||
hasMore: boolean
|
||||
offset: number
|
||||
}
|
||||
output: {
|
||||
contacts: any[]
|
||||
totalResults?: number
|
||||
pagination?: {
|
||||
hasMore: boolean
|
||||
offset: number
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export const contactsTool: ToolConfig<ContactsParams, ContactsResponse> = {
|
||||
@@ -115,9 +118,12 @@ export const contactsTool: ToolConfig<ContactsParams, ContactsResponse> = {
|
||||
transformResponse: async (response: Response) => {
|
||||
const data = await response.json()
|
||||
return {
|
||||
output: data.results || data,
|
||||
totalResults: data.total,
|
||||
pagination: data.paging
|
||||
success: true,
|
||||
output: {
|
||||
contacts: data.results || [data],
|
||||
totalResults: data.total,
|
||||
pagination: data.paging
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
+15
-9
@@ -1,4 +1,4 @@
|
||||
import { ToolConfig } from './types'
|
||||
import { ToolConfig, ToolResponse } from './types'
|
||||
import { chatTool as openAIChat } from './openai/chat'
|
||||
import { chatTool as anthropicChat } from './anthropic/chat'
|
||||
import { chatTool as googleChat } from './google/chat'
|
||||
@@ -42,11 +42,15 @@ export function getTool(toolId: string): ToolConfig | undefined {
|
||||
export async function executeTool(
|
||||
toolId: string,
|
||||
params: Record<string, any>
|
||||
): Promise<any> {
|
||||
): Promise<ToolResponse> {
|
||||
const tool = getTool(toolId)
|
||||
|
||||
if (!tool) {
|
||||
throw new Error(`Tool not found: ${toolId}`)
|
||||
return {
|
||||
success: false,
|
||||
output: {},
|
||||
error: `Tool not found: ${toolId}`
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
@@ -62,13 +66,15 @@ export async function executeTool(
|
||||
body: tool.request.body ? JSON.stringify(tool.request.body(params)) : undefined
|
||||
})
|
||||
|
||||
if (!response.ok) {
|
||||
const error = await response.json()
|
||||
throw new Error(tool.transformError(error))
|
||||
}
|
||||
// Transform the response
|
||||
const result = await tool.transformResponse(response)
|
||||
return result
|
||||
|
||||
return tool.transformResponse(response)
|
||||
} catch (error) {
|
||||
throw new Error(tool.transformError(error))
|
||||
return {
|
||||
success: false,
|
||||
output: {},
|
||||
error: tool.transformError(error)
|
||||
}
|
||||
}
|
||||
}
|
||||
+18
-9
@@ -15,9 +15,12 @@ interface ChatParams {
|
||||
}
|
||||
|
||||
interface ChatResponse extends ToolResponse {
|
||||
tokens?: number
|
||||
model: string
|
||||
reasoning_tokens?: number
|
||||
output: {
|
||||
content: string
|
||||
model: string
|
||||
tokens?: number
|
||||
reasoning_tokens?: number
|
||||
}
|
||||
}
|
||||
|
||||
export const chatTool: ToolConfig<ChatParams, ChatResponse> = {
|
||||
@@ -104,15 +107,21 @@ export const chatTool: ToolConfig<ChatParams, ChatResponse> = {
|
||||
const data = await response.json()
|
||||
if (data.choices?.[0]?.delta?.content) {
|
||||
return {
|
||||
output: data.choices[0].delta.content,
|
||||
model: data.model
|
||||
success: true,
|
||||
output: {
|
||||
content: data.choices[0].delta.content,
|
||||
model: data.model
|
||||
}
|
||||
}
|
||||
}
|
||||
return {
|
||||
output: data.choices[0].message.content,
|
||||
tokens: data.usage?.total_tokens,
|
||||
model: data.model,
|
||||
reasoning_tokens: data.usage?.completion_tokens_details?.reasoning_tokens
|
||||
success: true,
|
||||
output: {
|
||||
content: data.choices[0].message.content,
|
||||
model: data.model,
|
||||
tokens: data.usage?.total_tokens,
|
||||
reasoning_tokens: data.usage?.completion_tokens_details?.reasoning_tokens
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
@@ -17,11 +17,14 @@ interface OpportunityParams {
|
||||
}
|
||||
|
||||
interface OpportunityResponse extends ToolResponse {
|
||||
totalResults?: number
|
||||
pagination?: {
|
||||
hasMore: boolean
|
||||
offset: number
|
||||
}
|
||||
output: {
|
||||
records: any[]
|
||||
totalResults?: number
|
||||
pagination?: {
|
||||
hasMore: boolean
|
||||
offset: number
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export const opportunitiesTool: ToolConfig<OpportunityParams, OpportunityResponse> = {
|
||||
@@ -119,11 +122,14 @@ export const opportunitiesTool: ToolConfig<OpportunityParams, OpportunityRespons
|
||||
transformResponse: async (response: Response) => {
|
||||
const data = await response.json()
|
||||
return {
|
||||
output: data.records || data,
|
||||
totalResults: data.totalSize,
|
||||
pagination: {
|
||||
hasMore: !data.done,
|
||||
offset: data.nextRecordsUrl ? parseInt(data.nextRecordsUrl.split('-')[1]) : 0
|
||||
success: true,
|
||||
output: {
|
||||
records: data.records || [data],
|
||||
totalResults: data.totalSize,
|
||||
pagination: {
|
||||
hasMore: !data.done,
|
||||
offset: data.nextRecordsUrl ? parseInt(data.nextRecordsUrl.split('-')[1]) : 0
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
+3
-2
@@ -1,8 +1,9 @@
|
||||
export type HttpMethod = 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH'
|
||||
|
||||
export interface ToolResponse {
|
||||
output: any // All tools must provide an output field
|
||||
[key: string]: any // Tools can include additional metadata
|
||||
success: boolean // Whether the tool execution was successful
|
||||
output: Record<string, any> // The structured output from the tool
|
||||
error?: string // Error message if success is false
|
||||
}
|
||||
|
||||
export interface ToolConfig<P = any, R extends ToolResponse = ToolResponse> {
|
||||
|
||||
+13
-7
@@ -13,9 +13,12 @@ interface ChatParams {
|
||||
}
|
||||
|
||||
interface ChatResponse extends ToolResponse {
|
||||
tokens?: number
|
||||
model: string
|
||||
reasoning?: string
|
||||
output: {
|
||||
content: string
|
||||
model: string
|
||||
tokens?: number
|
||||
reasoning?: string
|
||||
}
|
||||
}
|
||||
|
||||
export const chatTool: ToolConfig<ChatParams, ChatResponse> = {
|
||||
@@ -83,10 +86,13 @@ export const chatTool: ToolConfig<ChatParams, ChatResponse> = {
|
||||
transformResponse: async (response: Response) => {
|
||||
const data = await response.json()
|
||||
return {
|
||||
output: data.choices[0].message.content,
|
||||
tokens: data.usage?.total_tokens,
|
||||
model: data.model,
|
||||
reasoning: data.choices[0]?.reasoning
|
||||
success: true,
|
||||
output: {
|
||||
content: data.choices[0].message.content,
|
||||
model: data.model,
|
||||
tokens: data.usage?.total_tokens,
|
||||
reasoning: data.choices[0]?.reasoning
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
Reference in New Issue
Block a user