@oh-my-pi/pi-coding-agent 6.2.0 → 6.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +46 -0
- package/docs/sdk.md +1 -1
- package/package.json +5 -5
- package/scripts/generate-template.ts +6 -6
- package/src/cli/args.ts +3 -0
- package/src/core/agent-session.ts +39 -0
- package/src/core/bash-executor.ts +3 -3
- package/src/core/cursor/exec-bridge.ts +95 -88
- package/src/core/custom-commands/bundled/review/index.ts +142 -145
- package/src/core/custom-commands/bundled/wt/index.ts +68 -66
- package/src/core/custom-commands/loader.ts +4 -6
- package/src/core/custom-tools/index.ts +2 -2
- package/src/core/custom-tools/loader.ts +66 -61
- package/src/core/custom-tools/types.ts +4 -4
- package/src/core/custom-tools/wrapper.ts +61 -25
- package/src/core/event-bus.ts +19 -47
- package/src/core/extensions/index.ts +8 -4
- package/src/core/extensions/loader.ts +160 -120
- package/src/core/extensions/types.ts +4 -4
- package/src/core/extensions/wrapper.ts +149 -100
- package/src/core/hooks/index.ts +1 -1
- package/src/core/hooks/tool-wrapper.ts +96 -70
- package/src/core/hooks/types.ts +1 -2
- package/src/core/index.ts +1 -0
- package/src/core/mcp/index.ts +6 -2
- package/src/core/mcp/json-rpc.ts +88 -0
- package/src/core/mcp/loader.ts +22 -4
- package/src/core/mcp/manager.ts +202 -48
- package/src/core/mcp/tool-bridge.ts +143 -55
- package/src/core/mcp/tool-cache.ts +122 -0
- package/src/core/python-executor.ts +3 -9
- package/src/core/sdk.ts +33 -32
- package/src/core/session-manager.ts +30 -0
- package/src/core/settings-manager.ts +34 -1
- package/src/core/ssh/ssh-executor.ts +6 -84
- package/src/core/streaming-output.ts +107 -53
- package/src/core/tools/ask.ts +92 -93
- package/src/core/tools/bash.ts +103 -94
- package/src/core/tools/calculator.ts +41 -26
- package/src/core/tools/complete.ts +76 -66
- package/src/core/tools/context.ts +22 -24
- package/src/core/tools/exa/index.ts +1 -1
- package/src/core/tools/exa/mcp-client.ts +56 -101
- package/src/core/tools/find.ts +250 -253
- package/src/core/tools/git.ts +39 -33
- package/src/core/tools/grep.ts +440 -427
- package/src/core/tools/index.ts +62 -61
- package/src/core/tools/ls.ts +119 -114
- package/src/core/tools/lsp/clients/biome-client.ts +5 -7
- package/src/core/tools/lsp/clients/index.ts +4 -4
- package/src/core/tools/lsp/clients/lsp-linter-client.ts +5 -7
- package/src/core/tools/lsp/config.ts +2 -2
- package/src/core/tools/lsp/index.ts +604 -578
- package/src/core/tools/notebook.ts +121 -119
- package/src/core/tools/output.ts +163 -147
- package/src/core/tools/patch/applicator.ts +1100 -0
- package/src/core/tools/patch/diff.ts +362 -0
- package/src/core/tools/patch/fuzzy.ts +647 -0
- package/src/core/tools/patch/index.ts +430 -0
- package/src/core/tools/patch/normalize.ts +220 -0
- package/src/core/tools/patch/normative.ts +49 -0
- package/src/core/tools/patch/parser.ts +528 -0
- package/src/core/tools/patch/shared.ts +228 -0
- package/src/core/tools/patch/types.ts +244 -0
- package/src/core/tools/python.ts +139 -136
- package/src/core/tools/read.ts +237 -216
- package/src/core/tools/render-utils.ts +196 -77
- package/src/core/tools/renderers.ts +1 -1
- package/src/core/tools/ssh.ts +99 -80
- package/src/core/tools/task/executor.ts +11 -7
- package/src/core/tools/task/index.ts +352 -343
- package/src/core/tools/task/worker.ts +13 -23
- package/src/core/tools/todo-write.ts +74 -59
- package/src/core/tools/web-fetch.ts +54 -47
- package/src/core/tools/web-search/index.ts +27 -16
- package/src/core/tools/write.ts +73 -44
- package/src/core/ttsr.ts +106 -152
- package/src/core/voice.ts +49 -39
- package/src/index.ts +16 -12
- package/src/lib/worktree/index.ts +1 -9
- package/src/modes/interactive/components/diff.ts +15 -8
- package/src/modes/interactive/components/settings-defs.ts +24 -0
- package/src/modes/interactive/components/tool-execution.ts +34 -6
- package/src/modes/interactive/controllers/event-controller.ts +6 -19
- package/src/modes/interactive/controllers/input-controller.ts +1 -1
- package/src/modes/interactive/utils/ui-helpers.ts +5 -1
- package/src/modes/rpc/rpc-mode.ts +99 -81
- package/src/prompts/tools/patch.md +76 -0
- package/src/prompts/tools/read.md +1 -1
- package/src/prompts/tools/{edit.md → replace.md} +1 -0
- package/src/utils/shell.ts +0 -40
- package/src/core/tools/edit-diff.ts +0 -574
- package/src/core/tools/edit.ts +0 -345
|
@@ -4,8 +4,9 @@
|
|
|
4
4
|
* Subagents must call this tool to finish and return structured JSON output.
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
import type { AgentTool } from "@oh-my-pi/pi-agent-core";
|
|
7
|
+
import type { AgentTool, AgentToolContext, AgentToolResult, AgentToolUpdateCallback } from "@oh-my-pi/pi-agent-core";
|
|
8
8
|
import { StringEnum } from "@oh-my-pi/pi-ai";
|
|
9
|
+
import type { Static, TObject } from "@sinclair/typebox";
|
|
9
10
|
import { Type } from "@sinclair/typebox";
|
|
10
11
|
import Ajv, { type ErrorObject, type ValidateFunction } from "ajv";
|
|
11
12
|
import type { ToolSession } from "./index";
|
|
@@ -52,77 +53,86 @@ function formatAjvErrors(errors: ErrorObject[] | null | undefined): string {
|
|
|
52
53
|
.join("; ");
|
|
53
54
|
}
|
|
54
55
|
|
|
55
|
-
export
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
56
|
+
export class CompleteTool implements AgentTool<TObject, CompleteDetails> {
|
|
57
|
+
public readonly name = "complete";
|
|
58
|
+
public readonly label = "Complete";
|
|
59
|
+
public readonly description =
|
|
60
|
+
"Finish the task with structured JSON output. Call exactly once at the end of the task.\n\n" +
|
|
61
|
+
"If you cannot complete the task, call with status='aborted' and an error message.";
|
|
62
|
+
public readonly parameters: TObject;
|
|
63
|
+
|
|
64
|
+
private readonly validate?: ValidateFunction;
|
|
65
|
+
private readonly schemaError?: string;
|
|
66
|
+
|
|
67
|
+
constructor(session: ToolSession) {
|
|
68
|
+
const schemaResult = normalizeSchema(session.outputSchema);
|
|
69
|
+
// Convert JTD to JSON Schema if needed (auto-detected)
|
|
70
|
+
const normalizedSchema =
|
|
71
|
+
schemaResult.normalized !== undefined ? jtdToJsonSchema(schemaResult.normalized) : undefined;
|
|
72
|
+
let schemaError = schemaResult.error;
|
|
73
|
+
|
|
74
|
+
if (normalizedSchema !== undefined && !schemaError) {
|
|
75
|
+
try {
|
|
76
|
+
this.validate = ajv.compile(normalizedSchema as any);
|
|
77
|
+
} catch (err) {
|
|
78
|
+
schemaError = err instanceof Error ? err.message : String(err);
|
|
79
|
+
}
|
|
68
80
|
}
|
|
81
|
+
|
|
82
|
+
this.schemaError = schemaError;
|
|
83
|
+
|
|
84
|
+
const schemaHint = formatSchema(normalizedSchema ?? session.outputSchema);
|
|
85
|
+
|
|
86
|
+
// Use actual schema if provided, otherwise fall back to Type.Any
|
|
87
|
+
// Merge description into the JSON schema for better tool documentation
|
|
88
|
+
const dataSchema = normalizedSchema
|
|
89
|
+
? Type.Unsafe({
|
|
90
|
+
...(normalizedSchema as object),
|
|
91
|
+
description: `Structured output matching the schema:\n${schemaHint}`,
|
|
92
|
+
})
|
|
93
|
+
: Type.Any({ description: "Structured JSON output (no schema specified)" });
|
|
94
|
+
|
|
95
|
+
this.parameters = Type.Object({
|
|
96
|
+
data: Type.Optional(dataSchema),
|
|
97
|
+
status: Type.Optional(
|
|
98
|
+
StringEnum(["success", "aborted"], {
|
|
99
|
+
description: "Use 'aborted' if the task cannot be completed, defaults to 'success'",
|
|
100
|
+
}),
|
|
101
|
+
),
|
|
102
|
+
error: Type.Optional(Type.String({ description: "Error message when status is 'aborted'" })),
|
|
103
|
+
});
|
|
69
104
|
}
|
|
70
105
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
status: Type.Optional(
|
|
85
|
-
StringEnum(["success", "aborted"], {
|
|
86
|
-
description: "Use 'aborted' if the task cannot be completed, defaults to 'success'",
|
|
87
|
-
}),
|
|
88
|
-
),
|
|
89
|
-
error: Type.Optional(Type.String({ description: "Error message when status is 'aborted'" })),
|
|
90
|
-
});
|
|
91
|
-
|
|
92
|
-
const tool: AgentTool<typeof completeParams, CompleteDetails> = {
|
|
93
|
-
name: "complete",
|
|
94
|
-
label: "Complete",
|
|
95
|
-
description:
|
|
96
|
-
"Finish the task with structured JSON output. Call exactly once at the end of the task.\n\n" +
|
|
97
|
-
"If you cannot complete the task, call with status='aborted' and an error message.",
|
|
98
|
-
parameters: completeParams,
|
|
99
|
-
execute: async (_toolCallId, params) => {
|
|
100
|
-
const status = params.status ?? "success";
|
|
101
|
-
|
|
102
|
-
// Skip validation when aborting - data is optional for aborts
|
|
103
|
-
if (status === "success") {
|
|
104
|
-
if (params.data === undefined) {
|
|
105
|
-
throw new Error("data is required when status is 'success'");
|
|
106
|
-
}
|
|
107
|
-
if (schemaError) {
|
|
108
|
-
throw new Error(`Invalid output schema: ${schemaError}`);
|
|
109
|
-
}
|
|
110
|
-
if (validate && !validate(params.data)) {
|
|
111
|
-
throw new Error(`Output does not match schema: ${formatAjvErrors(validate.errors)}`);
|
|
112
|
-
}
|
|
106
|
+
public async execute(
|
|
107
|
+
_toolCallId: string,
|
|
108
|
+
params: Static<TObject>,
|
|
109
|
+
_signal?: AbortSignal,
|
|
110
|
+
_onUpdate?: AgentToolUpdateCallback<CompleteDetails>,
|
|
111
|
+
_context?: AgentToolContext,
|
|
112
|
+
): Promise<AgentToolResult<CompleteDetails>> {
|
|
113
|
+
const status = (params.status ?? "success") as "success" | "aborted";
|
|
114
|
+
|
|
115
|
+
// Skip validation when aborting - data is optional for aborts
|
|
116
|
+
if (status === "success") {
|
|
117
|
+
if (params.data === undefined) {
|
|
118
|
+
throw new Error("data is required when status is 'success'");
|
|
113
119
|
}
|
|
120
|
+
if (this.schemaError) {
|
|
121
|
+
throw new Error(`Invalid output schema: ${this.schemaError}`);
|
|
122
|
+
}
|
|
123
|
+
if (this.validate && !this.validate(params.data)) {
|
|
124
|
+
throw new Error(`Output does not match schema: ${formatAjvErrors(this.validate.errors)}`);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
114
127
|
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
return {
|
|
119
|
-
content: [{ type: "text", text: responseText }],
|
|
120
|
-
details: { data: params.data, status, error: params.error },
|
|
121
|
-
};
|
|
122
|
-
},
|
|
123
|
-
};
|
|
128
|
+
const responseText =
|
|
129
|
+
status === "aborted" ? `Task aborted: ${params.error || "No reason provided"}` : "Completion recorded.";
|
|
124
130
|
|
|
125
|
-
|
|
131
|
+
return {
|
|
132
|
+
content: [{ type: "text", text: responseText }],
|
|
133
|
+
details: { data: params.data, status, error: params.error as string | undefined },
|
|
134
|
+
};
|
|
135
|
+
}
|
|
126
136
|
}
|
|
127
137
|
|
|
128
138
|
// Register subprocess tool handler for extraction + termination.
|
|
@@ -11,31 +11,29 @@ declare module "@oh-my-pi/pi-agent-core" {
|
|
|
11
11
|
}
|
|
12
12
|
}
|
|
13
13
|
|
|
14
|
-
export
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
}
|
|
14
|
+
export class ToolContextStore {
|
|
15
|
+
private uiContext: ExtensionUIContext | undefined;
|
|
16
|
+
private hasUI = false;
|
|
17
|
+
private toolNames: string[] = [];
|
|
19
18
|
|
|
20
|
-
|
|
21
|
-
let uiContext: ExtensionUIContext | undefined;
|
|
22
|
-
let hasUI = false;
|
|
23
|
-
let toolNames: string[] = [];
|
|
19
|
+
constructor(private readonly getBaseContext: () => CustomToolContext) {}
|
|
24
20
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
...getBaseContext(),
|
|
28
|
-
ui: uiContext,
|
|
29
|
-
hasUI,
|
|
30
|
-
toolNames,
|
|
21
|
+
getContext(toolCall?: ToolCallContext): AgentToolContext {
|
|
22
|
+
return {
|
|
23
|
+
...this.getBaseContext(),
|
|
24
|
+
ui: this.uiContext,
|
|
25
|
+
hasUI: this.hasUI,
|
|
26
|
+
toolNames: this.toolNames,
|
|
31
27
|
toolCall,
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
setUIContext(uiContext: ExtensionUIContext, hasUI: boolean): void {
|
|
32
|
+
this.uiContext = uiContext;
|
|
33
|
+
this.hasUI = hasUI;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
setToolNames(names: string[]): void {
|
|
37
|
+
this.toolNames = names;
|
|
38
|
+
}
|
|
41
39
|
}
|
|
@@ -48,11 +48,11 @@ export {
|
|
|
48
48
|
callExaTool,
|
|
49
49
|
callWebsetsTool,
|
|
50
50
|
createMCPToolFromServer,
|
|
51
|
-
createMCPWrappedTool,
|
|
52
51
|
fetchMCPToolSchema,
|
|
53
52
|
findApiKey,
|
|
54
53
|
formatSearchResults,
|
|
55
54
|
isSearchResponse,
|
|
55
|
+
MCPWrappedTool,
|
|
56
56
|
} from "./mcp-client";
|
|
57
57
|
export { renderExaCall, renderExaResult } from "./render";
|
|
58
58
|
export { researcherTools } from "./researcher";
|
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Exa MCP Client
|
|
3
3
|
*
|
|
4
|
-
* Client for interacting with Exa MCP servers
|
|
4
|
+
* Client for interacting with Exa MCP servers.
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
import { existsSync, readFileSync } from "node:fs";
|
|
8
8
|
import { homedir } from "node:os";
|
|
9
9
|
import type { TSchema } from "@sinclair/typebox";
|
|
10
|
-
import type { CustomTool } from "../../custom-tools/types";
|
|
10
|
+
import type { CustomTool, CustomToolResult } from "../../custom-tools/types";
|
|
11
11
|
import { logger } from "../../logger";
|
|
12
|
+
import { callMCP } from "../../mcp/json-rpc";
|
|
12
13
|
import type {
|
|
13
14
|
ExaRenderDetails,
|
|
14
15
|
ExaSearchResponse,
|
|
@@ -48,63 +49,6 @@ export async function findApiKey(): Promise<string | null> {
|
|
|
48
49
|
return null;
|
|
49
50
|
}
|
|
50
51
|
|
|
51
|
-
/** Parse SSE response format (lines starting with "data: ") */
|
|
52
|
-
function parseSSE(text: string): unknown {
|
|
53
|
-
const lines = text.split("\n");
|
|
54
|
-
for (const line of lines) {
|
|
55
|
-
if (line.startsWith("data: ")) {
|
|
56
|
-
const data = line.slice(6).trim();
|
|
57
|
-
if (data === "[DONE]") continue;
|
|
58
|
-
try {
|
|
59
|
-
return JSON.parse(data);
|
|
60
|
-
} catch {
|
|
61
|
-
// Try next line
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
// Fallback: try parsing entire response as JSON
|
|
66
|
-
try {
|
|
67
|
-
return JSON.parse(text);
|
|
68
|
-
} catch {
|
|
69
|
-
return null;
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
/** Call MCP server with JSON-RPC 2.0 */
|
|
74
|
-
export async function callMCP(url: string, method: string, params?: Record<string, unknown>): Promise<unknown> {
|
|
75
|
-
const body = {
|
|
76
|
-
jsonrpc: "2.0",
|
|
77
|
-
id: Math.random().toString(36).slice(2),
|
|
78
|
-
method,
|
|
79
|
-
params: params ?? {},
|
|
80
|
-
};
|
|
81
|
-
|
|
82
|
-
const response = await fetch(url, {
|
|
83
|
-
method: "POST",
|
|
84
|
-
headers: {
|
|
85
|
-
"Content-Type": "application/json",
|
|
86
|
-
Accept: "application/json, text/event-stream",
|
|
87
|
-
},
|
|
88
|
-
body: JSON.stringify(body),
|
|
89
|
-
});
|
|
90
|
-
|
|
91
|
-
if (!response.ok) {
|
|
92
|
-
const errorMsg = `MCP request failed: ${response.status} ${response.statusText}`;
|
|
93
|
-
logger.error(errorMsg, { url, method, params });
|
|
94
|
-
throw new Error(errorMsg);
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
const text = await response.text();
|
|
98
|
-
const result = parseSSE(text);
|
|
99
|
-
|
|
100
|
-
if (!result) {
|
|
101
|
-
logger.error("Failed to parse MCP response", { url, method, responseText: text.slice(0, 500) });
|
|
102
|
-
throw new Error("Failed to parse MCP response");
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
return result;
|
|
106
|
-
}
|
|
107
|
-
|
|
108
52
|
/** Fetch available tools from Exa MCP */
|
|
109
53
|
export async function fetchExaTools(apiKey: string, toolNames: string[]): Promise<MCPTool[]> {
|
|
110
54
|
const url = `https://mcp.exa.ai/mcp?exaApiKey=${encodeURIComponent(apiKey)}&toolNames=${encodeURIComponent(toolNames.join(","))}`;
|
|
@@ -299,56 +243,67 @@ export async function fetchMCPToolSchema(
|
|
|
299
243
|
}
|
|
300
244
|
|
|
301
245
|
/**
|
|
302
|
-
*
|
|
246
|
+
* CustomTool dynamically created from MCP tool metadata.
|
|
303
247
|
*
|
|
304
248
|
* This allows tools to be generated from MCP server schemas without hardcoding,
|
|
305
249
|
* reducing drift when MCP servers add new parameters.
|
|
306
250
|
*/
|
|
307
|
-
export
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
description: string
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
content: [{ type: "text" as const, text: "Error: EXA_API_KEY not found" }],
|
|
323
|
-
details: { error: "EXA_API_KEY not found", toolName: config.name },
|
|
324
|
-
};
|
|
325
|
-
}
|
|
326
|
-
|
|
327
|
-
const response = config.isWebsetsTool
|
|
328
|
-
? await callWebsetsTool(apiKey, config.mcpToolName, params as Record<string, unknown>)
|
|
329
|
-
: await callExaTool(config.mcpToolName, params as Record<string, unknown>, apiKey);
|
|
330
|
-
|
|
331
|
-
if (isSearchResponse(response)) {
|
|
332
|
-
const formatted = formatSearchResults(response);
|
|
333
|
-
return {
|
|
334
|
-
content: [{ type: "text" as const, text: formatted }],
|
|
335
|
-
details: { response, toolName: config.name },
|
|
336
|
-
};
|
|
337
|
-
}
|
|
251
|
+
export class MCPWrappedTool implements CustomTool<TSchema, ExaRenderDetails> {
|
|
252
|
+
public readonly name: string;
|
|
253
|
+
public readonly label: string;
|
|
254
|
+
public readonly description: string;
|
|
255
|
+
public readonly parameters: TSchema;
|
|
256
|
+
|
|
257
|
+
private readonly config: MCPToolWrapperConfig;
|
|
258
|
+
|
|
259
|
+
constructor(config: MCPToolWrapperConfig, schema: TSchema, description: string) {
|
|
260
|
+
this.config = config;
|
|
261
|
+
this.name = config.name;
|
|
262
|
+
this.label = config.label;
|
|
263
|
+
this.description = description;
|
|
264
|
+
this.parameters = schema;
|
|
265
|
+
}
|
|
338
266
|
|
|
267
|
+
async execute(
|
|
268
|
+
_toolCallId: string,
|
|
269
|
+
params: unknown,
|
|
270
|
+
_onUpdate?: unknown,
|
|
271
|
+
_ctx?: unknown,
|
|
272
|
+
_signal?: AbortSignal,
|
|
273
|
+
): Promise<CustomToolResult<ExaRenderDetails>> {
|
|
274
|
+
try {
|
|
275
|
+
const apiKey = await findApiKey();
|
|
276
|
+
if (!apiKey) {
|
|
339
277
|
return {
|
|
340
|
-
content: [{ type: "text" as const, text:
|
|
341
|
-
details: {
|
|
278
|
+
content: [{ type: "text" as const, text: "Error: EXA_API_KEY not found" }],
|
|
279
|
+
details: { error: "EXA_API_KEY not found", toolName: this.config.name },
|
|
342
280
|
};
|
|
343
|
-
}
|
|
344
|
-
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
const response = this.config.isWebsetsTool
|
|
284
|
+
? await callWebsetsTool(apiKey, this.config.mcpToolName, params as Record<string, unknown>)
|
|
285
|
+
: await callExaTool(this.config.mcpToolName, params as Record<string, unknown>, apiKey);
|
|
286
|
+
|
|
287
|
+
if (isSearchResponse(response)) {
|
|
288
|
+
const formatted = formatSearchResults(response);
|
|
345
289
|
return {
|
|
346
|
-
content: [{ type: "text" as const, text:
|
|
347
|
-
details: {
|
|
290
|
+
content: [{ type: "text" as const, text: formatted }],
|
|
291
|
+
details: { response, toolName: this.config.name },
|
|
348
292
|
};
|
|
349
293
|
}
|
|
350
|
-
|
|
351
|
-
|
|
294
|
+
|
|
295
|
+
return {
|
|
296
|
+
content: [{ type: "text" as const, text: JSON.stringify(response, null, 2) }],
|
|
297
|
+
details: { raw: response, toolName: this.config.name },
|
|
298
|
+
};
|
|
299
|
+
} catch (error) {
|
|
300
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
301
|
+
return {
|
|
302
|
+
content: [{ type: "text" as const, text: `Error: ${message}` }],
|
|
303
|
+
details: { error: message, toolName: this.config.name },
|
|
304
|
+
};
|
|
305
|
+
}
|
|
306
|
+
}
|
|
352
307
|
}
|
|
353
308
|
|
|
354
309
|
/**
|
|
@@ -361,9 +316,9 @@ export async function createMCPToolFromServer(
|
|
|
361
316
|
config: MCPToolWrapperConfig,
|
|
362
317
|
fallbackSchema: TSchema,
|
|
363
318
|
fallbackDescription: string,
|
|
364
|
-
): Promise<
|
|
319
|
+
): Promise<MCPWrappedTool> {
|
|
365
320
|
const mcpTool = await fetchMCPToolSchema(apiKey, config.mcpToolName, config.isWebsetsTool);
|
|
366
321
|
const schema = mcpTool?.inputSchema ?? fallbackSchema;
|
|
367
322
|
const description = mcpTool?.description ?? fallbackDescription;
|
|
368
|
-
return
|
|
323
|
+
return new MCPWrappedTool(config, schema, description);
|
|
369
324
|
}
|