servers: make tool call result spec compatible

This commit is contained in:
David Soria Parra
2024-12-02 13:12:15 +00:00
parent 87082db0f2
commit 788098220e
5 changed files with 269 additions and 329 deletions

View File

@@ -529,7 +529,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
case "fork_repository": { case "fork_repository": {
const args = ForkRepositorySchema.parse(request.params.arguments); const args = ForkRepositorySchema.parse(request.params.arguments);
const fork = await forkRepository(args.owner, args.repo, args.organization); const fork = await forkRepository(args.owner, args.repo, args.organization);
return { toolResult: fork }; return { content: [{ type: "text", text: JSON.stringify(fork, null, 2) }] };
} }
case "create_branch": { case "create_branch": {
@@ -562,25 +562,25 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
sha sha
}); });
return { toolResult: branch }; return { content: [{ type: "text", text: JSON.stringify(branch, null, 2) }] };
} }
case "search_repositories": { case "search_repositories": {
const args = SearchRepositoriesSchema.parse(request.params.arguments); const args = SearchRepositoriesSchema.parse(request.params.arguments);
const results = await searchRepositories(args.query, args.page, args.perPage); const results = await searchRepositories(args.query, args.page, args.perPage);
return { toolResult: results }; return { content: [{ type: "text", text: JSON.stringify(results, null, 2) }] };
} }
case "create_repository": { case "create_repository": {
const args = CreateRepositorySchema.parse(request.params.arguments); const args = CreateRepositorySchema.parse(request.params.arguments);
const repository = await createRepository(args); const repository = await createRepository(args);
return { toolResult: repository }; return { content: [{ type: "text", text: JSON.stringify(repository, null, 2) }] };
} }
case "get_file_contents": { case "get_file_contents": {
const args = GetFileContentsSchema.parse(request.params.arguments); const args = GetFileContentsSchema.parse(request.params.arguments);
const contents = await getFileContents(args.owner, args.repo, args.path, args.branch); const contents = await getFileContents(args.owner, args.repo, args.path, args.branch);
return { toolResult: contents }; return { content: [{ type: "text", text: JSON.stringify(contents, null, 2) }] };
} }
case "create_or_update_file": { case "create_or_update_file": {
@@ -594,7 +594,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
args.branch, args.branch,
args.sha args.sha
); );
return { toolResult: result }; return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
} }
case "push_files": { case "push_files": {
@@ -606,21 +606,21 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
args.files, args.files,
args.message args.message
); );
return { toolResult: result }; return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
} }
case "create_issue": { case "create_issue": {
const args = CreateIssueSchema.parse(request.params.arguments); const args = CreateIssueSchema.parse(request.params.arguments);
const { owner, repo, ...options } = args; const { owner, repo, ...options } = args;
const issue = await createIssue(owner, repo, options); const issue = await createIssue(owner, repo, options);
return { toolResult: issue }; return { content: [{ type: "text", text: JSON.stringify(issue, null, 2) }] };
} }
case "create_pull_request": { case "create_pull_request": {
const args = CreatePullRequestSchema.parse(request.params.arguments); const args = CreatePullRequestSchema.parse(request.params.arguments);
const { owner, repo, ...options } = args; const { owner, repo, ...options } = args;
const pullRequest = await createPullRequest(owner, repo, options); const pullRequest = await createPullRequest(owner, repo, options);
return { toolResult: pullRequest }; return { content: [{ type: "text", text: JSON.stringify(pullRequest, null, 2) }] };
} }
default: default:

View File

@@ -437,7 +437,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
case "fork_repository": { case "fork_repository": {
const args = ForkRepositorySchema.parse(request.params.arguments); const args = ForkRepositorySchema.parse(request.params.arguments);
const fork = await forkProject(args.project_id, args.namespace); const fork = await forkProject(args.project_id, args.namespace);
return { toolResult: fork }; return { content: [{ type: "text", text: JSON.stringify(fork, null, 2) }] };
} }
case "create_branch": { case "create_branch": {
@@ -452,25 +452,25 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
ref ref
}); });
return { toolResult: branch }; return { content: [{ type: "text", text: JSON.stringify(branch, null, 2) }] };
} }
case "search_repositories": { case "search_repositories": {
const args = SearchRepositoriesSchema.parse(request.params.arguments); const args = SearchRepositoriesSchema.parse(request.params.arguments);
const results = await searchProjects(args.search, args.page, args.per_page); const results = await searchProjects(args.search, args.page, args.per_page);
return { toolResult: results }; return { content: [{ type: "text", text: JSON.stringify(results, null, 2) }] };
} }
case "create_repository": { case "create_repository": {
const args = CreateRepositorySchema.parse(request.params.arguments); const args = CreateRepositorySchema.parse(request.params.arguments);
const repository = await createRepository(args); const repository = await createRepository(args);
return { toolResult: repository }; return { content: [{ type: "text", text: JSON.stringify(repository, null, 2) }] };
} }
case "get_file_contents": { case "get_file_contents": {
const args = GetFileContentsSchema.parse(request.params.arguments); const args = GetFileContentsSchema.parse(request.params.arguments);
const contents = await getFileContents(args.project_id, args.file_path, args.ref); const contents = await getFileContents(args.project_id, args.file_path, args.ref);
return { toolResult: contents }; return { content: [{ type: "text", text: JSON.stringify(contents, null, 2) }] };
} }
case "create_or_update_file": { case "create_or_update_file": {
@@ -483,7 +483,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
args.branch, args.branch,
args.previous_path args.previous_path
); );
return { toolResult: result }; return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
} }
case "push_files": { case "push_files": {
@@ -494,21 +494,21 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
args.branch, args.branch,
args.files.map(f => ({ path: f.file_path, content: f.content })) args.files.map(f => ({ path: f.file_path, content: f.content }))
); );
return { toolResult: result }; return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
} }
case "create_issue": { case "create_issue": {
const args = CreateIssueSchema.parse(request.params.arguments); const args = CreateIssueSchema.parse(request.params.arguments);
const { project_id, ...options } = args; const { project_id, ...options } = args;
const issue = await createIssue(project_id, options); const issue = await createIssue(project_id, options);
return { toolResult: issue }; return { content: [{ type: "text", text: JSON.stringify(issue, null, 2) }] };
} }
case "create_merge_request": { case "create_merge_request": {
const args = CreateMergeRequestSchema.parse(request.params.arguments); const args = CreateMergeRequestSchema.parse(request.params.arguments);
const { project_id, ...options } = args; const { project_id, ...options } = args;
const mergeRequest = await createMergeRequest(project_id, options); const mergeRequest = await createMergeRequest(project_id, options);
return { toolResult: mergeRequest }; return { content: [{ type: "text", text: JSON.stringify(mergeRequest, null, 2) }] };
} }
default: default:

View File

@@ -141,7 +141,7 @@ function getApiKey(): string {
} }
return apiKey; return apiKey;
} }
const GOOGLE_MAPS_API_KEY = getApiKey(); const GOOGLE_MAPS_API_KEY = getApiKey();
// Tool definitions // Tool definitions
@@ -151,28 +151,28 @@ const GEOCODE_TOOL: Tool = {
inputSchema: { inputSchema: {
type: "object", type: "object",
properties: { properties: {
address: { address: {
type: "string", type: "string",
description: "The address to geocode" description: "The address to geocode"
} }
}, },
required: ["address"] required: ["address"]
} }
}; };
const REVERSE_GEOCODE_TOOL: Tool = { const REVERSE_GEOCODE_TOOL: Tool = {
name: "maps_reverse_geocode", name: "maps_reverse_geocode",
description: "Convert coordinates into an address", description: "Convert coordinates into an address",
inputSchema: { inputSchema: {
type: "object", type: "object",
properties: { properties: {
latitude: { latitude: {
type: "number", type: "number",
description: "Latitude coordinate" description: "Latitude coordinate"
}, },
longitude: { longitude: {
type: "number", type: "number",
description: "Longitude coordinate" description: "Longitude coordinate"
} }
}, },
required: ["latitude", "longitude"] required: ["latitude", "longitude"]
@@ -185,9 +185,9 @@ const SEARCH_PLACES_TOOL: Tool = {
inputSchema: { inputSchema: {
type: "object", type: "object",
properties: { properties: {
query: { query: {
type: "string", type: "string",
description: "Search query" description: "Search query"
}, },
location: { location: {
type: "object", type: "object",
@@ -225,7 +225,7 @@ const DISTANCE_MATRIX_TOOL: Tool = {
name: "maps_distance_matrix", name: "maps_distance_matrix",
description: "Calculate travel distance and time for multiple origins and destinations", description: "Calculate travel distance and time for multiple origins and destinations",
inputSchema: { inputSchema: {
type: "object", type: "object",
properties: { properties: {
origins: { origins: {
type: "array", type: "array",
@@ -233,7 +233,7 @@ const DISTANCE_MATRIX_TOOL: Tool = {
description: "Array of origin addresses or coordinates" description: "Array of origin addresses or coordinates"
}, },
destinations: { destinations: {
type: "array", type: "array",
items: { type: "string" }, items: { type: "string" },
description: "Array of destination addresses or coordinates" description: "Array of destination addresses or coordinates"
}, },
@@ -276,13 +276,13 @@ const DIRECTIONS_TOOL: Tool = {
inputSchema: { inputSchema: {
type: "object", type: "object",
properties: { properties: {
origin: { origin: {
type: "string", type: "string",
description: "Starting point address or coordinates" description: "Starting point address or coordinates"
}, },
destination: { destination: {
type: "string", type: "string",
description: "Ending point address or coordinates" description: "Ending point address or coordinates"
}, },
mode: { mode: {
type: "string", type: "string",
@@ -315,28 +315,24 @@ async function handleGeocode(address: string) {
if (data.status !== "OK") { if (data.status !== "OK") {
return { return {
toolResult: { content: [{
content: [{ type: "text",
type: "text", text: `Geocoding failed: ${data.error_message || data.status}`
text: `Geocoding failed: ${data.error_message || data.status}` }],
}], isError: true
isError: true
}
}; };
} }
return { return {
toolResult: { content: [{
content: [{ type: "text",
type: "text", text: JSON.stringify({
text: JSON.stringify({ location: data.results[0].geometry.location,
location: data.results[0].geometry.location, formatted_address: data.results[0].formatted_address,
formatted_address: data.results[0].formatted_address, place_id: data.results[0].place_id
place_id: data.results[0].place_id }, null, 2)
}, null, 2) }],
}], isError: false
isError: false
}
}; };
} }
@@ -350,28 +346,24 @@ async function handleReverseGeocode(latitude: number, longitude: number) {
if (data.status !== "OK") { if (data.status !== "OK") {
return { return {
toolResult: { content: [{
content: [{ type: "text",
type: "text", text: `Reverse geocoding failed: ${data.error_message || data.status}`
text: `Reverse geocoding failed: ${data.error_message || data.status}` }],
}], isError: true
isError: true
}
}; };
} }
return { return {
toolResult: { content: [{
content: [{ type: "text",
type: "text", text: JSON.stringify({
text: JSON.stringify({ formatted_address: data.results[0].formatted_address,
formatted_address: data.results[0].formatted_address, place_id: data.results[0].place_id,
place_id: data.results[0].place_id, address_components: data.results[0].address_components
address_components: data.results[0].address_components }, null, 2)
}, null, 2) }],
}], isError: false
isError: false
}
}; };
} }
@@ -396,33 +388,29 @@ async function handlePlaceSearch(
if (data.status !== "OK") { if (data.status !== "OK") {
return { return {
toolResult: { content: [{
content: [{ type: "text",
type: "text", text: `Place search failed: ${data.error_message || data.status}`
text: `Place search failed: ${data.error_message || data.status}` }],
}], isError: true
isError: true
}
}; };
} }
return { return {
toolResult: { content: [{
content: [{ type: "text",
type: "text", text: JSON.stringify({
text: JSON.stringify({ places: data.results.map((place) => ({
places: data.results.map((place) => ({ name: place.name,
name: place.name, formatted_address: place.formatted_address,
formatted_address: place.formatted_address, location: place.geometry.location,
location: place.geometry.location, place_id: place.place_id,
place_id: place.place_id, rating: place.rating,
rating: place.rating, types: place.types
types: place.types }))
})) }, null, 2)
}, null, 2) }],
}], isError: false
isError: false
}
}; };
} }
@@ -436,33 +424,29 @@ async function handlePlaceDetails(place_id: string) {
if (data.status !== "OK") { if (data.status !== "OK") {
return { return {
toolResult: { content: [{
content: [{ type: "text",
type: "text", text: `Place details request failed: ${data.error_message || data.status}`
text: `Place details request failed: ${data.error_message || data.status}` }],
}], isError: true
isError: true
}
}; };
} }
return { return {
toolResult: { content: [{
content: [{ type: "text",
type: "text", text: JSON.stringify({
text: JSON.stringify({ name: data.result.name,
name: data.result.name, formatted_address: data.result.formatted_address,
formatted_address: data.result.formatted_address, location: data.result.geometry.location,
location: data.result.geometry.location, formatted_phone_number: data.result.formatted_phone_number,
formatted_phone_number: data.result.formatted_phone_number, website: data.result.website,
website: data.result.website, rating: data.result.rating,
rating: data.result.rating, reviews: data.result.reviews,
reviews: data.result.reviews, opening_hours: data.result.opening_hours
opening_hours: data.result.opening_hours }, null, 2)
}, null, 2) }],
}], isError: false
isError: false
}
}; };
} }
async function handleDistanceMatrix( async function handleDistanceMatrix(
@@ -481,34 +465,30 @@ async function handleDistanceMatrix(
if (data.status !== "OK") { if (data.status !== "OK") {
return { return {
toolResult: { content: [{
content: [{ type: "text",
type: "text", text: `Distance matrix request failed: ${data.error_message || data.status}`
text: `Distance matrix request failed: ${data.error_message || data.status}` }],
}], isError: true
isError: true
}
}; };
} }
return { return {
toolResult: { content: [{
content: [{ type: "text",
type: "text", text: JSON.stringify({
text: JSON.stringify({ origin_addresses: data.origin_addresses,
origin_addresses: data.origin_addresses, destination_addresses: data.destination_addresses,
destination_addresses: data.destination_addresses, results: data.rows.map((row) => ({
results: data.rows.map((row) => ({ elements: row.elements.map((element) => ({
elements: row.elements.map((element) => ({ status: element.status,
status: element.status, duration: element.duration,
duration: element.duration, distance: element.distance
distance: element.distance
}))
})) }))
}, null, 2) }))
}], }, null, 2)
isError: false }],
} isError: false
}; };
} }
@@ -525,30 +505,26 @@ async function handleElevation(locations: Array<{ latitude: number; longitude: n
if (data.status !== "OK") { if (data.status !== "OK") {
return { return {
toolResult: { content: [{
content: [{ type: "text",
type: "text", text: `Elevation request failed: ${data.error_message || data.status}`
text: `Elevation request failed: ${data.error_message || data.status}` }],
}], isError: true
isError: true
}
}; };
} }
return { return {
toolResult: { content: [{
content: [{ type: "text",
type: "text", text: JSON.stringify({
text: JSON.stringify({ results: data.results.map((result) => ({
results: data.results.map((result) => ({ elevation: result.elevation,
elevation: result.elevation, location: result.location,
location: result.location, resolution: result.resolution
resolution: result.resolution }))
})) }, null, 2)
}, null, 2) }],
}], isError: false
isError: false
}
}; };
} }
@@ -568,36 +544,32 @@ async function handleDirections(
if (data.status !== "OK") { if (data.status !== "OK") {
return { return {
toolResult: { content: [{
content: [{ type: "text",
type: "text", text: `Directions request failed: ${data.error_message || data.status}`
text: `Directions request failed: ${data.error_message || data.status}` }],
}], isError: true
isError: true
}
}; };
} }
return { return {
toolResult: { content: [{
content: [{ type: "text",
type: "text", text: JSON.stringify({
text: JSON.stringify({ routes: data.routes.map((route) => ({
routes: data.routes.map((route) => ({ summary: route.summary,
summary: route.summary, distance: route.legs[0].distance,
distance: route.legs[0].distance, duration: route.legs[0].duration,
duration: route.legs[0].duration, steps: route.legs[0].steps.map((step) => ({
steps: route.legs[0].steps.map((step) => ({ instructions: step.html_instructions,
instructions: step.html_instructions, distance: step.distance,
distance: step.distance, duration: step.duration,
duration: step.duration, travel_mode: step.travel_mode
travel_mode: step.travel_mode
}))
})) }))
}, null, 2) }))
}], }, null, 2)
isError: false }],
} isError: false
}; };
} }
@@ -626,7 +598,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
const { address } = request.params.arguments as { address: string }; const { address } = request.params.arguments as { address: string };
return await handleGeocode(address); return await handleGeocode(address);
} }
case "maps_reverse_geocode": { case "maps_reverse_geocode": {
const { latitude, longitude } = request.params.arguments as { const { latitude, longitude } = request.params.arguments as {
latitude: number; latitude: number;
@@ -634,7 +606,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
}; };
return await handleReverseGeocode(latitude, longitude); return await handleReverseGeocode(latitude, longitude);
} }
case "maps_search_places": { case "maps_search_places": {
const { query, location, radius } = request.params.arguments as { const { query, location, radius } = request.params.arguments as {
query: string; query: string;
@@ -643,12 +615,12 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
}; };
return await handlePlaceSearch(query, location, radius); return await handlePlaceSearch(query, location, radius);
} }
case "maps_place_details": { case "maps_place_details": {
const { place_id } = request.params.arguments as { place_id: string }; const { place_id } = request.params.arguments as { place_id: string };
return await handlePlaceDetails(place_id); return await handlePlaceDetails(place_id);
} }
case "maps_distance_matrix": { case "maps_distance_matrix": {
const { origins, destinations, mode } = request.params.arguments as { const { origins, destinations, mode } = request.params.arguments as {
origins: string[]; origins: string[];
@@ -657,14 +629,14 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
}; };
return await handleDistanceMatrix(origins, destinations, mode); return await handleDistanceMatrix(origins, destinations, mode);
} }
case "maps_elevation": { case "maps_elevation": {
const { locations } = request.params.arguments as { const { locations } = request.params.arguments as {
locations: Array<{ latitude: number; longitude: number }>; locations: Array<{ latitude: number; longitude: number }>;
}; };
return await handleElevation(locations); return await handleElevation(locations);
} }
case "maps_directions": { case "maps_directions": {
const { origin, destination, mode } = request.params.arguments as { const { origin, destination, mode } = request.params.arguments as {
origin: string; origin: string;
@@ -673,27 +645,23 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
}; };
return await handleDirections(origin, destination, mode); return await handleDirections(origin, destination, mode);
} }
default: default:
return { return {
toolResult: { content: [{
content: [{ type: "text",
type: "text", text: `Unknown tool: ${request.params.name}`
text: `Unknown tool: ${request.params.name}` }],
}], isError: true
isError: true
}
}; };
} }
} catch (error) { } catch (error) {
return { return {
toolResult: { content: [{
content: [{ type: "text",
type: "text", text: `Error: ${error instanceof Error ? error.message : String(error)}`
text: `Error: ${error instanceof Error ? error.message : String(error)}` }],
}], isError: true
isError: true
}
}; };
} }
}); });
@@ -707,4 +675,4 @@ async function runServer() {
runServer().catch((error) => { runServer().catch((error) => {
console.error("Fatal error running server:", error); console.error("Fatal error running server:", error);
process.exit(1); process.exit(1);
}); });

View File

@@ -377,26 +377,26 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
switch (name) { switch (name) {
case "create_entities": case "create_entities":
return { toolResult: await knowledgeGraphManager.createEntities(args.entities as Entity[]) }; return { content: [{ type: "text", text: JSON.stringify(await knowledgeGraphManager.createEntities(args.entities as Entity[]), null, 2) }] };
case "create_relations": case "create_relations":
return { toolResult: await knowledgeGraphManager.createRelations(args.relations as Relation[]) }; return { content: [{ type: "text", text: JSON.stringify(await knowledgeGraphManager.createRelations(args.relations as Relation[]), null, 2) }] };
case "add_observations": case "add_observations":
return { toolResult: await knowledgeGraphManager.addObservations(args.observations as { entityName: string; contents: string[] }[]) }; return { content: [{ type: "text", text: JSON.stringify(await knowledgeGraphManager.addObservations(args.observations as { entityName: string; contents: string[] }[]), null, 2) }] };
case "delete_entities": case "delete_entities":
await knowledgeGraphManager.deleteEntities(args.entityNames as string[]); await knowledgeGraphManager.deleteEntities(args.entityNames as string[]);
return { toolResult: "Entities deleted successfully" }; return { content: [{ type: "text", text: "Entities deleted successfully" }] };
case "delete_observations": case "delete_observations":
await knowledgeGraphManager.deleteObservations(args.deletions as { entityName: string; observations: string[] }[]); await knowledgeGraphManager.deleteObservations(args.deletions as { entityName: string; observations: string[] }[]);
return { toolResult: "Observations deleted successfully" }; return { content: [{ type: "text", text: "Observations deleted successfully" }] };
case "delete_relations": case "delete_relations":
await knowledgeGraphManager.deleteRelations(args.relations as Relation[]); await knowledgeGraphManager.deleteRelations(args.relations as Relation[]);
return { toolResult: "Relations deleted successfully" }; return { content: [{ type: "text", text: "Relations deleted successfully" }] };
case "read_graph": case "read_graph":
return { toolResult: await knowledgeGraphManager.readGraph() }; return { content: [{ type: "text", text: JSON.stringify(await knowledgeGraphManager.readGraph(), null, 2) }] };
case "search_nodes": case "search_nodes":
return { toolResult: await knowledgeGraphManager.searchNodes(args.query as string) }; return { content: [{ type: "text", text: JSON.stringify(await knowledgeGraphManager.searchNodes(args.query as string), null, 2) }] };
case "open_nodes": case "open_nodes":
return { toolResult: await knowledgeGraphManager.openNodes(args.names as string[]) }; return { content: [{ type: "text", text: JSON.stringify(await knowledgeGraphManager.openNodes(args.names as string[]), null, 2) }] };
default: default:
throw new Error(`Unknown tool: ${name}`); throw new Error(`Unknown tool: ${name}`);
} }

View File

@@ -124,20 +124,18 @@ async function ensureBrowser() {
return page!; return page!;
} }
async function handleToolCall(name: string, args: any): Promise<{ toolResult: CallToolResult }> { async function handleToolCall(name: string, args: any): Promise<CallToolResult> {
const page = await ensureBrowser(); const page = await ensureBrowser();
switch (name) { switch (name) {
case "puppeteer_navigate": case "puppeteer_navigate":
await page.goto(args.url); await page.goto(args.url);
return { return {
toolResult: { content: [{
content: [{ type: "text",
type: "text", text: `Navigated to ${args.url}`,
text: `Navigated to ${args.url}`, }],
}], isError: false,
isError: false,
},
}; };
case "puppeteer_screenshot": { case "puppeteer_screenshot": {
@@ -151,13 +149,11 @@ async function handleToolCall(name: string, args: any): Promise<{ toolResult: Ca
if (!screenshot) { if (!screenshot) {
return { return {
toolResult: { content: [{
content: [{ type: "text",
type: "text", text: args.selector ? `Element not found: ${args.selector}` : "Screenshot failed",
text: args.selector ? `Element not found: ${args.selector}` : "Screenshot failed", }],
}], isError: true,
isError: true,
},
}; };
} }
@@ -167,20 +163,18 @@ async function handleToolCall(name: string, args: any): Promise<{ toolResult: Ca
}); });
return { return {
toolResult: { content: [
content: [ {
{ type: "text",
type: "text", text: `Screenshot '${args.name}' taken at ${width}x${height}`,
text: `Screenshot '${args.name}' taken at ${width}x${height}`, } as TextContent,
} as TextContent, {
{ type: "image",
type: "image", data: screenshot,
data: screenshot, mimeType: "image/png",
mimeType: "image/png", } as ImageContent,
} as ImageContent, ],
], isError: false,
isError: false,
},
}; };
} }
@@ -188,23 +182,19 @@ async function handleToolCall(name: string, args: any): Promise<{ toolResult: Ca
try { try {
await page.click(args.selector); await page.click(args.selector);
return { return {
toolResult: { content: [{
content: [{ type: "text",
type: "text", text: `Clicked: ${args.selector}`,
text: `Clicked: ${args.selector}`, }],
}], isError: false,
isError: false,
},
}; };
} catch (error) { } catch (error) {
return { return {
toolResult: { content: [{
content: [{ type: "text",
type: "text", text: `Failed to click ${args.selector}: ${(error as Error).message}`,
text: `Failed to click ${args.selector}: ${(error as Error).message}`, }],
}], isError: true,
isError: true,
},
}; };
} }
@@ -213,23 +203,19 @@ async function handleToolCall(name: string, args: any): Promise<{ toolResult: Ca
await page.waitForSelector(args.selector); await page.waitForSelector(args.selector);
await page.type(args.selector, args.value); await page.type(args.selector, args.value);
return { return {
toolResult: { content: [{
content: [{ type: "text",
type: "text", text: `Filled ${args.selector} with: ${args.value}`,
text: `Filled ${args.selector} with: ${args.value}`, }],
}], isError: false,
isError: false,
},
}; };
} catch (error) { } catch (error) {
return { return {
toolResult: { content: [{
content: [{ type: "text",
type: "text", text: `Failed to fill ${args.selector}: ${(error as Error).message}`,
text: `Failed to fill ${args.selector}: ${(error as Error).message}`, }],
}], isError: true,
isError: true,
},
}; };
} }
@@ -238,23 +224,19 @@ async function handleToolCall(name: string, args: any): Promise<{ toolResult: Ca
await page.waitForSelector(args.selector); await page.waitForSelector(args.selector);
await page.select(args.selector, args.value); await page.select(args.selector, args.value);
return { return {
toolResult: { content: [{
content: [{ type: "text",
type: "text", text: `Selected ${args.selector} with: ${args.value}`,
text: `Selected ${args.selector} with: ${args.value}`, }],
}], isError: false,
isError: false,
},
}; };
} catch (error) { } catch (error) {
return { return {
toolResult: { content: [{
content: [{ type: "text",
type: "text", text: `Failed to select ${args.selector}: ${(error as Error).message}`,
text: `Failed to select ${args.selector}: ${(error as Error).message}`, }],
}], isError: true,
isError: true,
},
}; };
} }
@@ -263,23 +245,19 @@ async function handleToolCall(name: string, args: any): Promise<{ toolResult: Ca
await page.waitForSelector(args.selector); await page.waitForSelector(args.selector);
await page.hover(args.selector); await page.hover(args.selector);
return { return {
toolResult: { content: [{
content: [{ type: "text",
type: "text", text: `Hovered ${args.selector}`,
text: `Hovered ${args.selector}`, }],
}], isError: false,
isError: false,
},
}; };
} catch (error) { } catch (error) {
return { return {
toolResult: { content: [{
content: [{ type: "text",
type: "text", text: `Failed to hover ${args.selector}: ${(error as Error).message}`,
text: `Failed to hover ${args.selector}: ${(error as Error).message}`, }],
}], isError: true,
isError: true,
},
}; };
} }
@@ -307,37 +285,31 @@ async function handleToolCall(name: string, args: any): Promise<{ toolResult: Ca
}, args.script); }, args.script);
return { return {
toolResult: { content: [
content: [ {
{ type: "text",
type: "text", text: `Execution result:\n${JSON.stringify(result.result, null, 2)}\n\nConsole output:\n${result.logs.join('\n')}`,
text: `Execution result:\n${JSON.stringify(result.result, null, 2)}\n\nConsole output:\n${result.logs.join('\n')}`, },
}, ],
], isError: false,
isError: false,
},
}; };
} catch (error) { } catch (error) {
return { return {
toolResult: { content: [{
content: [{ type: "text",
type: "text", text: `Script execution failed: ${(error as Error).message}`,
text: `Script execution failed: ${(error as Error).message}`, }],
}], isError: true,
isError: true,
},
}; };
} }
default: default:
return { return {
toolResult: { content: [{
content: [{ type: "text",
type: "text", text: `Unknown tool: ${name}`,
text: `Unknown tool: ${name}`, }],
}], isError: true,
isError: true,
},
}; };
} }
} }