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:
Waleed Latif
2025-01-30 13:50:38 -08:00
parent 15b42c7d19
commit 3850c112ca
31 changed files with 798 additions and 775 deletions
+11 -5
View File
@@ -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
View File
@@ -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
View File
@@ -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
}
}
},
+11 -7
View File
@@ -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
}
}
},
+7 -5
View File
@@ -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
}
}
},
+18 -7
View File
@@ -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
View File
@@ -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
View File
@@ -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
}
}
},
+14 -8
View File
@@ -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
View File
@@ -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
View File
@@ -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
}
}
},
+16 -10
View File
@@ -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
View File
@@ -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
View File
@@ -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
}
}
},