@iqai/adk 0.2.0 → 0.2.1
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 +7 -0
- package/dist/index.d.mts +124 -111
- package/dist/index.d.ts +124 -111
- package/dist/index.js +1415 -1401
- package/dist/index.mjs +1418 -1404
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -3879,6 +3879,7 @@ __export(tools_exports, {
|
|
|
3879
3879
|
McpAbi: () => McpAbi,
|
|
3880
3880
|
McpAtp: () => McpAtp,
|
|
3881
3881
|
McpBamm: () => McpBamm,
|
|
3882
|
+
McpClientService: () => McpClientService,
|
|
3882
3883
|
McpCoinGecko: () => McpCoinGecko,
|
|
3883
3884
|
McpDiscord: () => McpDiscord,
|
|
3884
3885
|
McpError: () => McpError,
|
|
@@ -3894,6 +3895,7 @@ __export(tools_exports, {
|
|
|
3894
3895
|
McpSamplingHandler: () => McpSamplingHandler,
|
|
3895
3896
|
McpTelegram: () => McpTelegram,
|
|
3896
3897
|
McpToolset: () => McpToolset,
|
|
3898
|
+
McpUpbit: () => McpUpbit,
|
|
3897
3899
|
ToolContext: () => ToolContext,
|
|
3898
3900
|
TransferToAgentTool: () => TransferToAgentTool,
|
|
3899
3901
|
UserInteractionTool: () => UserInteractionTool,
|
|
@@ -3907,1015 +3909,954 @@ __export(tools_exports, {
|
|
|
3907
3909
|
mcpSchemaToParameters: () => mcpSchemaToParameters,
|
|
3908
3910
|
normalizeJsonSchema: () => normalizeJsonSchema
|
|
3909
3911
|
});
|
|
3910
|
-
init_base_tool();
|
|
3911
3912
|
|
|
3912
|
-
// src/tools/
|
|
3913
|
-
|
|
3914
|
-
var
|
|
3915
|
-
var
|
|
3916
|
-
var
|
|
3913
|
+
// src/tools/mcp/client.ts
|
|
3914
|
+
init_logger();
|
|
3915
|
+
var _indexjs = require('@modelcontextprotocol/sdk/client/index.js');
|
|
3916
|
+
var _ssejs = require('@modelcontextprotocol/sdk/client/sse.js');
|
|
3917
|
+
var _stdiojs = require('@modelcontextprotocol/sdk/client/stdio.js');
|
|
3918
|
+
var _typesjs = require('@modelcontextprotocol/sdk/types.js');
|
|
3919
|
+
|
|
3920
|
+
// src/tools/mcp/sampling-handler.ts
|
|
3921
|
+
init_logger();
|
|
3922
|
+
|
|
3923
|
+
|
|
3924
|
+
|
|
3925
|
+
|
|
3926
|
+
|
|
3927
|
+
// src/tools/mcp/types.ts
|
|
3928
|
+
var McpErrorType = /* @__PURE__ */ ((McpErrorType2) => {
|
|
3929
|
+
McpErrorType2["CONNECTION_ERROR"] = "connection_error";
|
|
3930
|
+
McpErrorType2["TOOL_EXECUTION_ERROR"] = "tool_execution_error";
|
|
3931
|
+
McpErrorType2["RESOURCE_CLOSED_ERROR"] = "resource_closed_error";
|
|
3932
|
+
McpErrorType2["TIMEOUT_ERROR"] = "timeout_error";
|
|
3933
|
+
McpErrorType2["INVALID_SCHEMA_ERROR"] = "invalid_schema_error";
|
|
3934
|
+
McpErrorType2["SAMPLING_ERROR"] = "SAMPLING_ERROR";
|
|
3935
|
+
McpErrorType2["INVALID_REQUEST_ERROR"] = "INVALID_REQUEST_ERROR";
|
|
3936
|
+
return McpErrorType2;
|
|
3937
|
+
})(McpErrorType || {});
|
|
3938
|
+
var McpError = class extends Error {
|
|
3917
3939
|
|
|
3918
3940
|
|
|
3941
|
+
constructor(message, type, originalError) {
|
|
3942
|
+
super(message);
|
|
3943
|
+
this.name = "McpError";
|
|
3944
|
+
this.type = type;
|
|
3945
|
+
this.originalError = originalError;
|
|
3946
|
+
}
|
|
3947
|
+
};
|
|
3948
|
+
|
|
3949
|
+
// src/tools/mcp/sampling-handler.ts
|
|
3950
|
+
var McpSamplingHandler = (_class13 = class {
|
|
3951
|
+
__init22() {this.logger = new Logger({ name: "McpSamplingHandler" })}
|
|
3919
3952
|
|
|
3920
|
-
constructor(
|
|
3921
|
-
|
|
3922
|
-
name: config.name,
|
|
3923
|
-
description: config.description,
|
|
3924
|
-
isLongRunning: _nullishCoalesce(config.isLongRunning, () => ( false)),
|
|
3925
|
-
shouldRetryOnFailure: _nullishCoalesce(config.shouldRetryOnFailure, () => ( false)),
|
|
3926
|
-
maxRetryAttempts: _nullishCoalesce(config.maxRetryAttempts, () => ( 3))
|
|
3927
|
-
});
|
|
3928
|
-
this.func = config.fn;
|
|
3929
|
-
this.schema = _nullishCoalesce(config.schema, () => ( z.object({})));
|
|
3930
|
-
this.functionDeclaration = this.buildDeclaration();
|
|
3953
|
+
constructor(samplingHandler) {;_class13.prototype.__init22.call(this);
|
|
3954
|
+
this.samplingHandler = samplingHandler;
|
|
3931
3955
|
}
|
|
3932
3956
|
/**
|
|
3933
|
-
*
|
|
3957
|
+
* Handle MCP sampling request and convert between formats
|
|
3934
3958
|
*/
|
|
3935
|
-
async
|
|
3959
|
+
async handleSamplingRequest(request) {
|
|
3936
3960
|
try {
|
|
3937
|
-
|
|
3938
|
-
|
|
3939
|
-
|
|
3961
|
+
if (request.method !== "sampling/createMessage") {
|
|
3962
|
+
this.logger.error(
|
|
3963
|
+
`Invalid method for sampling handler: ${request.method}. Expected: sampling/createMessage`
|
|
3964
|
+
);
|
|
3965
|
+
throw new McpError(
|
|
3966
|
+
`Invalid method: ${request.method}. This handler only processes sampling/createMessage requests.`,
|
|
3967
|
+
"INVALID_REQUEST_ERROR" /* INVALID_REQUEST_ERROR */
|
|
3968
|
+
);
|
|
3969
|
+
}
|
|
3970
|
+
const validationResult = _typesjs.CreateMessageRequestSchema.safeParse(request);
|
|
3971
|
+
if (!validationResult.success) {
|
|
3972
|
+
this.logger.error(
|
|
3973
|
+
"Invalid MCP sampling request:",
|
|
3974
|
+
validationResult.error
|
|
3975
|
+
);
|
|
3976
|
+
throw new McpError(
|
|
3977
|
+
`Invalid sampling request: ${validationResult.error.message}`,
|
|
3978
|
+
"INVALID_REQUEST_ERROR" /* INVALID_REQUEST_ERROR */
|
|
3979
|
+
);
|
|
3980
|
+
}
|
|
3981
|
+
const mcpParams = request.params;
|
|
3982
|
+
if (!mcpParams.messages || !Array.isArray(mcpParams.messages)) {
|
|
3983
|
+
throw new McpError(
|
|
3984
|
+
"Invalid sampling request: messages array is required",
|
|
3985
|
+
"INVALID_REQUEST_ERROR" /* INVALID_REQUEST_ERROR */
|
|
3986
|
+
);
|
|
3987
|
+
}
|
|
3988
|
+
if (!mcpParams.maxTokens || mcpParams.maxTokens <= 0) {
|
|
3989
|
+
throw new McpError(
|
|
3990
|
+
"Invalid sampling request: maxTokens must be a positive number",
|
|
3991
|
+
"INVALID_REQUEST_ERROR" /* INVALID_REQUEST_ERROR */
|
|
3992
|
+
);
|
|
3993
|
+
}
|
|
3994
|
+
this.logger.debug("Converting MCP request to ADK format");
|
|
3995
|
+
const adkContents = this.convertMcpMessagesToADK(
|
|
3996
|
+
mcpParams.messages,
|
|
3997
|
+
mcpParams.systemPrompt
|
|
3998
|
+
);
|
|
3999
|
+
const requestModel = mcpParams.model || "gemini-2.0-flash";
|
|
4000
|
+
const adkRequest = new LlmRequest({
|
|
4001
|
+
model: requestModel,
|
|
4002
|
+
contents: adkContents,
|
|
4003
|
+
config: {
|
|
4004
|
+
temperature: mcpParams.temperature,
|
|
4005
|
+
maxOutputTokens: mcpParams.maxTokens
|
|
4006
|
+
}
|
|
4007
|
+
});
|
|
4008
|
+
this.logger.debug("Calling ADK sampling handler");
|
|
4009
|
+
const adkResponse = await this.samplingHandler(adkRequest);
|
|
4010
|
+
this.logger.debug("Converting ADK response to MCP format");
|
|
4011
|
+
const mcpResponse = this.convertADKResponseToMcp(
|
|
4012
|
+
adkResponse,
|
|
4013
|
+
requestModel
|
|
4014
|
+
);
|
|
4015
|
+
const responseValidation = _typesjs.CreateMessageResultSchema.safeParse(mcpResponse);
|
|
4016
|
+
if (!responseValidation.success) {
|
|
4017
|
+
this.logger.error(
|
|
4018
|
+
"Invalid MCP response generated:",
|
|
4019
|
+
responseValidation.error
|
|
4020
|
+
);
|
|
4021
|
+
throw new McpError(
|
|
4022
|
+
`Invalid response generated: ${responseValidation.error.message}`,
|
|
4023
|
+
"SAMPLING_ERROR" /* SAMPLING_ERROR */
|
|
4024
|
+
);
|
|
4025
|
+
}
|
|
4026
|
+
return mcpResponse;
|
|
3940
4027
|
} catch (error) {
|
|
3941
|
-
|
|
3942
|
-
|
|
3943
|
-
|
|
3944
|
-
};
|
|
4028
|
+
this.logger.error("Error handling sampling request:", error);
|
|
4029
|
+
if (error instanceof McpError) {
|
|
4030
|
+
throw error;
|
|
3945
4031
|
}
|
|
3946
|
-
|
|
3947
|
-
|
|
3948
|
-
|
|
4032
|
+
throw new McpError(
|
|
4033
|
+
`Sampling request failed: ${error instanceof Error ? error.message : String(error)}`,
|
|
4034
|
+
"SAMPLING_ERROR" /* SAMPLING_ERROR */,
|
|
4035
|
+
error instanceof Error ? error : void 0
|
|
4036
|
+
);
|
|
3949
4037
|
}
|
|
3950
4038
|
}
|
|
3951
4039
|
/**
|
|
3952
|
-
*
|
|
4040
|
+
* Convert MCP messages to ADK Content format
|
|
3953
4041
|
*/
|
|
3954
|
-
|
|
3955
|
-
|
|
4042
|
+
convertMcpMessagesToADK(mcpMessages, systemPrompt) {
|
|
4043
|
+
const contents = [];
|
|
4044
|
+
if (systemPrompt) {
|
|
4045
|
+
contents.push({
|
|
4046
|
+
role: "user",
|
|
4047
|
+
// System messages are typically sent as user role in content
|
|
4048
|
+
parts: [{ text: systemPrompt }]
|
|
4049
|
+
});
|
|
4050
|
+
}
|
|
4051
|
+
const transformedMessages = mcpMessages.map(
|
|
4052
|
+
(mcpMessage) => this.convertSingleMcpMessageToADK(mcpMessage)
|
|
4053
|
+
);
|
|
4054
|
+
contents.push(...transformedMessages);
|
|
4055
|
+
return contents;
|
|
3956
4056
|
}
|
|
3957
4057
|
/**
|
|
3958
|
-
*
|
|
4058
|
+
* Convert a single MCP message to ADK Content format
|
|
3959
4059
|
*/
|
|
3960
|
-
|
|
3961
|
-
const
|
|
3962
|
-
|
|
3963
|
-
|
|
3964
|
-
|
|
3965
|
-
|
|
3966
|
-
return {
|
|
3967
|
-
name: this.name,
|
|
3968
|
-
description: this.description,
|
|
3969
|
-
parameters
|
|
4060
|
+
convertSingleMcpMessageToADK(mcpMessage) {
|
|
4061
|
+
const adkRole = mcpMessage.role === "assistant" ? "model" : "user";
|
|
4062
|
+
const adkParts = this.convertMcpContentToADKParts(mcpMessage.content);
|
|
4063
|
+
const adkContent = {
|
|
4064
|
+
role: adkRole,
|
|
4065
|
+
parts: adkParts
|
|
3970
4066
|
};
|
|
4067
|
+
this.logger.debug(
|
|
4068
|
+
`Converted MCP message - role: ${mcpMessage.role} -> ${adkRole}, content type: ${mcpMessage.content.type}`
|
|
4069
|
+
);
|
|
4070
|
+
return adkContent;
|
|
3971
4071
|
}
|
|
3972
|
-
};
|
|
3973
|
-
function createTool(config) {
|
|
3974
|
-
return new CreatedTool(config);
|
|
3975
|
-
}
|
|
3976
|
-
|
|
3977
|
-
// src/tools/common/agent-tool.ts
|
|
3978
|
-
init_logger();
|
|
3979
|
-
|
|
3980
|
-
|
|
3981
|
-
|
|
3982
|
-
// src/agents/invocation-context.ts
|
|
3983
|
-
var LlmCallsLimitExceededError = class extends Error {
|
|
3984
|
-
constructor(message) {
|
|
3985
|
-
super(message);
|
|
3986
|
-
this.name = "LlmCallsLimitExceededError";
|
|
3987
|
-
}
|
|
3988
|
-
};
|
|
3989
|
-
var InvocationCostManager = (_class13 = class {constructor() { _class13.prototype.__init22.call(this); }
|
|
3990
|
-
/**
|
|
3991
|
-
* A counter that keeps track of number of llm calls made.
|
|
3992
|
-
*/
|
|
3993
|
-
__init22() {this._numberOfLlmCalls = 0}
|
|
3994
4072
|
/**
|
|
3995
|
-
*
|
|
4073
|
+
* Convert MCP message content to ADK parts format
|
|
3996
4074
|
*/
|
|
3997
|
-
|
|
3998
|
-
|
|
3999
|
-
|
|
4000
|
-
|
|
4001
|
-
|
|
4002
|
-
|
|
4075
|
+
convertMcpContentToADKParts(mcpContent) {
|
|
4076
|
+
if (mcpContent.type === "text") {
|
|
4077
|
+
const textContent = mcpContent.text || "";
|
|
4078
|
+
return [{ text: textContent }];
|
|
4079
|
+
}
|
|
4080
|
+
if (mcpContent.type === "image") {
|
|
4081
|
+
const parts = [];
|
|
4082
|
+
if (mcpContent.text && typeof mcpContent.text === "string") {
|
|
4083
|
+
parts.push({ text: mcpContent.text });
|
|
4084
|
+
}
|
|
4085
|
+
if (mcpContent.data && typeof mcpContent.data === "string") {
|
|
4086
|
+
const mimeType = mcpContent.mimeType || "image/jpeg";
|
|
4087
|
+
parts.push({
|
|
4088
|
+
inlineData: {
|
|
4089
|
+
data: mcpContent.data,
|
|
4090
|
+
mimeType
|
|
4091
|
+
}
|
|
4092
|
+
});
|
|
4093
|
+
}
|
|
4094
|
+
return parts.length > 0 ? parts : [{ text: "" }];
|
|
4003
4095
|
}
|
|
4096
|
+
this.logger.warn(`Unknown MCP content type: ${mcpContent.type}`);
|
|
4097
|
+
const fallbackText = typeof mcpContent.data === "string" ? mcpContent.data : "";
|
|
4098
|
+
return [{ text: fallbackText }];
|
|
4004
4099
|
}
|
|
4005
|
-
}, _class13);
|
|
4006
|
-
function newInvocationContextId() {
|
|
4007
|
-
return `e-${crypto.randomUUID()}`;
|
|
4008
|
-
}
|
|
4009
|
-
var InvocationContext = (_class14 = class _InvocationContext {
|
|
4010
|
-
|
|
4011
|
-
|
|
4012
|
-
|
|
4013
|
-
/**
|
|
4014
|
-
* The id of this invocation context. Readonly.
|
|
4015
|
-
*/
|
|
4016
|
-
|
|
4017
|
-
/**
|
|
4018
|
-
* The branch of the invocation context.
|
|
4019
|
-
*
|
|
4020
|
-
* The format is like agent_1.agent_2.agent_3, where agent_1 is the parent of
|
|
4021
|
-
* agent_2, and agent_2 is the parent of agent_3.
|
|
4022
|
-
*
|
|
4023
|
-
* Branch is used when multiple sub-agents shouldn't see their peer agents'
|
|
4024
|
-
* conversation history.
|
|
4025
|
-
*/
|
|
4026
|
-
|
|
4027
4100
|
/**
|
|
4028
|
-
*
|
|
4101
|
+
* Convert ADK response to MCP response format
|
|
4029
4102
|
*/
|
|
4030
|
-
|
|
4031
|
-
|
|
4032
|
-
|
|
4033
|
-
|
|
4034
|
-
|
|
4035
|
-
|
|
4036
|
-
|
|
4037
|
-
|
|
4038
|
-
|
|
4039
|
-
|
|
4040
|
-
|
|
4041
|
-
|
|
4042
|
-
|
|
4043
|
-
|
|
4044
|
-
|
|
4045
|
-
|
|
4046
|
-
|
|
4047
|
-
|
|
4048
|
-
|
|
4049
|
-
|
|
4050
|
-
|
|
4051
|
-
|
|
4052
|
-
|
|
4053
|
-
|
|
4054
|
-
|
|
4055
|
-
|
|
4056
|
-
|
|
4057
|
-
/**
|
|
4058
|
-
* Configurations for live agents under this invocation.
|
|
4059
|
-
*/
|
|
4060
|
-
|
|
4061
|
-
/**
|
|
4062
|
-
* A container to keep track of different kinds of costs incurred as a part
|
|
4063
|
-
* of this invocation.
|
|
4064
|
-
*/
|
|
4065
|
-
__init24() {this._invocationCostManager = new InvocationCostManager()}
|
|
4066
|
-
/**
|
|
4067
|
-
* Constructor for InvocationContext
|
|
4068
|
-
*/
|
|
4069
|
-
constructor(options) {;_class14.prototype.__init23.call(this);_class14.prototype.__init24.call(this);
|
|
4070
|
-
this.artifactService = options.artifactService;
|
|
4071
|
-
this.sessionService = options.sessionService;
|
|
4072
|
-
this.memoryService = options.memoryService;
|
|
4073
|
-
this.invocationId = options.invocationId || newInvocationContextId();
|
|
4074
|
-
this.branch = options.branch;
|
|
4075
|
-
this.agent = options.agent;
|
|
4076
|
-
this.userContent = options.userContent;
|
|
4077
|
-
this.session = options.session;
|
|
4078
|
-
this.endInvocation = options.endInvocation || false;
|
|
4079
|
-
this.liveRequestQueue = options.liveRequestQueue;
|
|
4080
|
-
this.activeStreamingTools = options.activeStreamingTools;
|
|
4081
|
-
this.transcriptionCache = options.transcriptionCache;
|
|
4082
|
-
this.runConfig = options.runConfig;
|
|
4083
|
-
}
|
|
4084
|
-
/**
|
|
4085
|
-
* App name from the session
|
|
4086
|
-
*/
|
|
4087
|
-
get appName() {
|
|
4088
|
-
return this.session.appName;
|
|
4089
|
-
}
|
|
4090
|
-
/**
|
|
4091
|
-
* User ID from the session
|
|
4092
|
-
*/
|
|
4093
|
-
get userId() {
|
|
4094
|
-
return this.session.userId;
|
|
4095
|
-
}
|
|
4096
|
-
/**
|
|
4097
|
-
* Tracks number of llm calls made.
|
|
4098
|
-
*
|
|
4099
|
-
* @throws {LlmCallsLimitExceededError} If number of llm calls made exceed the set threshold.
|
|
4100
|
-
*/
|
|
4101
|
-
incrementLlmCallCount() {
|
|
4102
|
-
this._invocationCostManager.incrementAndEnforceLlmCallsLimit(
|
|
4103
|
-
this.runConfig
|
|
4104
|
-
);
|
|
4103
|
+
convertADKResponseToMcp(adkResponse, model) {
|
|
4104
|
+
let responseText = "";
|
|
4105
|
+
if (typeof adkResponse === "string") {
|
|
4106
|
+
responseText = adkResponse;
|
|
4107
|
+
} else {
|
|
4108
|
+
if (adkResponse.content) {
|
|
4109
|
+
if (typeof adkResponse.content === "string") {
|
|
4110
|
+
responseText = adkResponse.content;
|
|
4111
|
+
} else if (adkResponse.content.parts) {
|
|
4112
|
+
responseText = adkResponse.content.parts.map((part) => {
|
|
4113
|
+
return typeof part.text === "string" ? part.text : "";
|
|
4114
|
+
}).join("");
|
|
4115
|
+
}
|
|
4116
|
+
}
|
|
4117
|
+
}
|
|
4118
|
+
const mcpResponse = {
|
|
4119
|
+
model,
|
|
4120
|
+
// Use the model from the request
|
|
4121
|
+
role: "assistant",
|
|
4122
|
+
// ADK responses are always from assistant
|
|
4123
|
+
content: {
|
|
4124
|
+
type: "text",
|
|
4125
|
+
text: responseText
|
|
4126
|
+
}
|
|
4127
|
+
};
|
|
4128
|
+
this.logger.debug(`Received content: ${responseText}`);
|
|
4129
|
+
return mcpResponse;
|
|
4105
4130
|
}
|
|
4106
4131
|
/**
|
|
4107
|
-
*
|
|
4132
|
+
* Update the ADK handler
|
|
4108
4133
|
*/
|
|
4109
|
-
|
|
4110
|
-
|
|
4111
|
-
|
|
4112
|
-
sessionService: this.sessionService,
|
|
4113
|
-
memoryService: this.memoryService,
|
|
4114
|
-
invocationId: this.invocationId,
|
|
4115
|
-
// Keep same invocation ID
|
|
4116
|
-
branch: this.branch ? `${this.branch}.${agent.name}` : agent.name,
|
|
4117
|
-
// Update branch
|
|
4118
|
-
agent,
|
|
4119
|
-
// Update to the new agent
|
|
4120
|
-
userContent: this.userContent,
|
|
4121
|
-
session: this.session,
|
|
4122
|
-
endInvocation: this.endInvocation,
|
|
4123
|
-
liveRequestQueue: this.liveRequestQueue,
|
|
4124
|
-
activeStreamingTools: this.activeStreamingTools,
|
|
4125
|
-
transcriptionCache: this.transcriptionCache,
|
|
4126
|
-
runConfig: this.runConfig
|
|
4127
|
-
});
|
|
4134
|
+
updateHandler(handler) {
|
|
4135
|
+
this.samplingHandler = handler;
|
|
4136
|
+
this.logger.debug("ADK sampling handler updated");
|
|
4128
4137
|
}
|
|
4129
|
-
},
|
|
4138
|
+
}, _class13);
|
|
4139
|
+
function createSamplingHandler(handler) {
|
|
4140
|
+
return handler;
|
|
4141
|
+
}
|
|
4130
4142
|
|
|
4131
|
-
// src/tools/
|
|
4132
|
-
|
|
4133
|
-
|
|
4134
|
-
|
|
4143
|
+
// src/tools/mcp/utils.ts
|
|
4144
|
+
function withRetry(fn, instance, reinitMethod, maxRetries = 1) {
|
|
4145
|
+
return async (...args) => {
|
|
4146
|
+
let attempt = 0;
|
|
4147
|
+
while (attempt <= maxRetries) {
|
|
4148
|
+
try {
|
|
4149
|
+
return await fn.apply(instance, args);
|
|
4150
|
+
} catch (error) {
|
|
4151
|
+
const isClosedResourceError = error instanceof Error && (error.message.includes("closed") || error.message.includes("ECONNRESET") || error.message.includes("socket hang up"));
|
|
4152
|
+
if (!isClosedResourceError || attempt >= maxRetries) {
|
|
4153
|
+
throw error;
|
|
4154
|
+
}
|
|
4155
|
+
console.warn(
|
|
4156
|
+
`Resource closed, reinitializing (attempt ${attempt + 1}/${maxRetries + 1})...`
|
|
4157
|
+
);
|
|
4158
|
+
try {
|
|
4159
|
+
await reinitMethod(instance);
|
|
4160
|
+
} catch (reinitError) {
|
|
4161
|
+
console.error("Error reinitializing resources:", reinitError);
|
|
4162
|
+
throw new Error(`Failed to reinitialize resources: ${reinitError}`);
|
|
4163
|
+
}
|
|
4164
|
+
attempt++;
|
|
4165
|
+
}
|
|
4166
|
+
}
|
|
4167
|
+
throw new Error("Unexpected end of retry loop");
|
|
4168
|
+
};
|
|
4135
4169
|
}
|
|
4136
|
-
|
|
4137
|
-
|
|
4138
|
-
|
|
4139
|
-
|
|
4140
|
-
|
|
4141
|
-
|
|
4142
|
-
|
|
4143
|
-
|
|
4144
|
-
|
|
4145
|
-
|
|
4146
|
-
|
|
4147
|
-
|
|
4148
|
-
|
|
4149
|
-
|
|
4150
|
-
* Whether to skip summarization of the agent's response
|
|
4151
|
-
*/
|
|
4152
|
-
|
|
4153
|
-
__init25() {this.logger = new Logger({ name: "AgentTool" })}
|
|
4154
|
-
/**
|
|
4155
|
-
* Create a new agent tool
|
|
4156
|
-
*/
|
|
4157
|
-
constructor(config) {
|
|
4158
|
-
super({
|
|
4159
|
-
name: config.name,
|
|
4160
|
-
description: config.description || config.agent.description,
|
|
4161
|
-
isLongRunning: config.isLongRunning || false,
|
|
4162
|
-
shouldRetryOnFailure: config.shouldRetryOnFailure || false,
|
|
4163
|
-
maxRetryAttempts: config.maxRetryAttempts || 3
|
|
4164
|
-
});_class15.prototype.__init25.call(this);;
|
|
4165
|
-
this.agent = config.agent;
|
|
4166
|
-
this.functionDeclaration = config.functionDeclaration;
|
|
4167
|
-
this.outputKey = config.outputKey;
|
|
4168
|
-
this.skipSummarization = config.skipSummarization || false;
|
|
4170
|
+
|
|
4171
|
+
// src/tools/mcp/client.ts
|
|
4172
|
+
var McpClientService = (_class14 = class {
|
|
4173
|
+
|
|
4174
|
+
__init23() {this.client = null}
|
|
4175
|
+
__init24() {this.transport = null}
|
|
4176
|
+
__init25() {this.isClosing = false}
|
|
4177
|
+
__init26() {this.mcpSamplingHandler = null}
|
|
4178
|
+
__init27() {this.logger = new Logger({ name: "McpClientService" })}
|
|
4179
|
+
constructor(config) {;_class14.prototype.__init23.call(this);_class14.prototype.__init24.call(this);_class14.prototype.__init25.call(this);_class14.prototype.__init26.call(this);_class14.prototype.__init27.call(this);
|
|
4180
|
+
this.config = config;
|
|
4181
|
+
if (config.samplingHandler) {
|
|
4182
|
+
this.mcpSamplingHandler = new McpSamplingHandler(config.samplingHandler);
|
|
4183
|
+
}
|
|
4169
4184
|
}
|
|
4170
4185
|
/**
|
|
4171
|
-
*
|
|
4186
|
+
* Initializes and returns an MCP client based on configuration.
|
|
4187
|
+
* Will create a new client if one doesn't exist yet.
|
|
4172
4188
|
*/
|
|
4173
|
-
|
|
4174
|
-
if (this.
|
|
4175
|
-
|
|
4189
|
+
async initialize() {
|
|
4190
|
+
if (this.isClosing) {
|
|
4191
|
+
throw new McpError(
|
|
4192
|
+
"Cannot initialize a client that is being closed",
|
|
4193
|
+
"resource_closed_error" /* RESOURCE_CLOSED_ERROR */
|
|
4194
|
+
);
|
|
4176
4195
|
}
|
|
4177
|
-
|
|
4178
|
-
|
|
4179
|
-
|
|
4180
|
-
|
|
4181
|
-
|
|
4182
|
-
|
|
4183
|
-
|
|
4184
|
-
|
|
4185
|
-
|
|
4186
|
-
|
|
4187
|
-
|
|
4196
|
+
if (this.client) {
|
|
4197
|
+
return this.client;
|
|
4198
|
+
}
|
|
4199
|
+
try {
|
|
4200
|
+
if (!this.transport) {
|
|
4201
|
+
this.transport = await this.createTransport();
|
|
4202
|
+
}
|
|
4203
|
+
const client = new (0, _indexjs.Client)(
|
|
4204
|
+
{
|
|
4205
|
+
name: this.config.name,
|
|
4206
|
+
version: "0.0.1"
|
|
4188
4207
|
},
|
|
4189
|
-
|
|
4208
|
+
{
|
|
4209
|
+
capabilities: {
|
|
4210
|
+
prompts: {},
|
|
4211
|
+
resources: {},
|
|
4212
|
+
tools: {},
|
|
4213
|
+
sampling: {}
|
|
4214
|
+
// Enable sampling capability
|
|
4215
|
+
}
|
|
4216
|
+
}
|
|
4217
|
+
);
|
|
4218
|
+
const connectPromise = client.connect(this.transport);
|
|
4219
|
+
if (this.config.timeout) {
|
|
4220
|
+
const timeoutPromise = new Promise((_, reject) => {
|
|
4221
|
+
setTimeout(() => {
|
|
4222
|
+
reject(
|
|
4223
|
+
new McpError(
|
|
4224
|
+
`MCP client connection timed out after ${this.config.timeout}ms`,
|
|
4225
|
+
"timeout_error" /* TIMEOUT_ERROR */
|
|
4226
|
+
)
|
|
4227
|
+
);
|
|
4228
|
+
}, this.config.timeout);
|
|
4229
|
+
});
|
|
4230
|
+
await Promise.race([connectPromise, timeoutPromise]);
|
|
4231
|
+
} else {
|
|
4232
|
+
await connectPromise;
|
|
4190
4233
|
}
|
|
4191
|
-
|
|
4234
|
+
await this.setupSamplingHandler(client);
|
|
4235
|
+
this.logger.debug("\u2705 MCP client connected successfully");
|
|
4236
|
+
this.client = client;
|
|
4237
|
+
return client;
|
|
4238
|
+
} catch (error) {
|
|
4239
|
+
await this.cleanupResources();
|
|
4240
|
+
if (!(error instanceof McpError)) {
|
|
4241
|
+
this.logger.error("Failed to initialize MCP client:", error);
|
|
4242
|
+
throw new McpError(
|
|
4243
|
+
`Failed to initialize MCP client: ${error instanceof Error ? error.message : String(error)}`,
|
|
4244
|
+
"connection_error" /* CONNECTION_ERROR */,
|
|
4245
|
+
error instanceof Error ? error : void 0
|
|
4246
|
+
);
|
|
4247
|
+
}
|
|
4248
|
+
throw error;
|
|
4249
|
+
}
|
|
4192
4250
|
}
|
|
4193
4251
|
/**
|
|
4194
|
-
*
|
|
4252
|
+
* Creates a transport based on the configuration.
|
|
4195
4253
|
*/
|
|
4196
|
-
async
|
|
4254
|
+
async createTransport() {
|
|
4197
4255
|
try {
|
|
4198
|
-
|
|
4199
|
-
|
|
4200
|
-
|
|
4201
|
-
|
|
4256
|
+
if (this.config.transport.mode === "sse") {
|
|
4257
|
+
this.logger.debug(
|
|
4258
|
+
"\u{1F680} Initializing MCP client in SSE mode",
|
|
4259
|
+
this.config.transport.serverUrl
|
|
4260
|
+
);
|
|
4261
|
+
const headers = {
|
|
4262
|
+
...this.config.transport.headers || {},
|
|
4263
|
+
...this.config.headers || {}
|
|
4264
|
+
};
|
|
4265
|
+
return new (0, _ssejs.SSEClientTransport)(
|
|
4266
|
+
new URL(this.config.transport.serverUrl),
|
|
4267
|
+
{
|
|
4268
|
+
requestInit: {
|
|
4269
|
+
headers,
|
|
4270
|
+
...this.config.timeout ? { timeout: this.config.timeout } : {}
|
|
4271
|
+
}
|
|
4272
|
+
}
|
|
4202
4273
|
);
|
|
4203
4274
|
}
|
|
4204
|
-
|
|
4205
|
-
|
|
4206
|
-
|
|
4207
|
-
|
|
4208
|
-
|
|
4209
|
-
|
|
4210
|
-
|
|
4211
|
-
|
|
4212
|
-
runConfig: parentInvocation.runConfig,
|
|
4213
|
-
userContent: {
|
|
4214
|
-
role: "user",
|
|
4215
|
-
parts: [{ text: String(input) }]
|
|
4216
|
-
},
|
|
4217
|
-
branch: parentInvocation.branch ? `${parentInvocation.branch}.${this.agent.name}` : this.agent.name
|
|
4275
|
+
this.logger.debug(
|
|
4276
|
+
"\u{1F680} Initializing MCP client in STDIO mode",
|
|
4277
|
+
this.config.transport.command
|
|
4278
|
+
);
|
|
4279
|
+
return new (0, _stdiojs.StdioClientTransport)({
|
|
4280
|
+
command: this.config.transport.command,
|
|
4281
|
+
args: this.config.transport.args,
|
|
4282
|
+
env: this.config.transport.env
|
|
4218
4283
|
});
|
|
4219
|
-
let lastEvent = null;
|
|
4220
|
-
for await (const event of this.agent.runAsync(childInvocationContext)) {
|
|
4221
|
-
if (!event.partial) {
|
|
4222
|
-
await childInvocationContext.sessionService.appendEvent(
|
|
4223
|
-
childInvocationContext.session,
|
|
4224
|
-
event
|
|
4225
|
-
);
|
|
4226
|
-
}
|
|
4227
|
-
if (event.content && event.author === this.agent.name) {
|
|
4228
|
-
lastEvent = event;
|
|
4229
|
-
}
|
|
4230
|
-
}
|
|
4231
|
-
if (!lastEvent || !lastEvent.content || !lastEvent.content.parts) {
|
|
4232
|
-
return "";
|
|
4233
|
-
}
|
|
4234
|
-
const mergedText = lastEvent.content.parts.filter((part) => part.text !== void 0 && part.text !== null).map((part) => part.text).join("\n");
|
|
4235
|
-
let toolResult;
|
|
4236
|
-
try {
|
|
4237
|
-
toolResult = JSON.parse(mergedText);
|
|
4238
|
-
} catch (e2) {
|
|
4239
|
-
toolResult = mergedText;
|
|
4240
|
-
}
|
|
4241
|
-
if (this.outputKey && _optionalChain([context4, 'optionalAccess', _145 => _145.state])) {
|
|
4242
|
-
context4.state[this.outputKey] = toolResult;
|
|
4243
|
-
}
|
|
4244
|
-
return toolResult;
|
|
4245
4284
|
} catch (error) {
|
|
4246
|
-
|
|
4247
|
-
|
|
4248
|
-
|
|
4285
|
+
throw new McpError(
|
|
4286
|
+
`Failed to create transport: ${error instanceof Error ? error.message : String(error)}`,
|
|
4287
|
+
"connection_error" /* CONNECTION_ERROR */,
|
|
4288
|
+
error instanceof Error ? error : void 0
|
|
4249
4289
|
);
|
|
4250
4290
|
}
|
|
4251
4291
|
}
|
|
4252
|
-
}, _class15);
|
|
4253
|
-
|
|
4254
|
-
// src/tools/tool-context.ts
|
|
4255
|
-
var ToolContext = class extends CallbackContext {
|
|
4256
|
-
/**
|
|
4257
|
-
* The function call id of the current tool call. This id was
|
|
4258
|
-
* returned in the function call event from LLM to identify a function call.
|
|
4259
|
-
* If LLM didn't return this id, ADK will assign one to it. This id is used
|
|
4260
|
-
* to map function call response to the original function call.
|
|
4261
|
-
*/
|
|
4262
|
-
|
|
4263
|
-
/**
|
|
4264
|
-
* Constructor for ToolContext
|
|
4265
|
-
*/
|
|
4266
|
-
constructor(invocationContext, options = {}) {
|
|
4267
|
-
super(invocationContext, { eventActions: options.eventActions });
|
|
4268
|
-
this.functionCallId = options.functionCallId;
|
|
4269
|
-
}
|
|
4270
|
-
/**
|
|
4271
|
-
* Gets the event actions of the current tool call
|
|
4272
|
-
*/
|
|
4273
|
-
get actions() {
|
|
4274
|
-
return this.eventActions;
|
|
4275
|
-
}
|
|
4276
|
-
/**
|
|
4277
|
-
* Lists the filenames of the artifacts attached to the current session
|
|
4278
|
-
*/
|
|
4279
|
-
async listArtifacts() {
|
|
4280
|
-
if (!this._invocationContext.artifactService) {
|
|
4281
|
-
throw new Error("Artifact service is not initialized.");
|
|
4282
|
-
}
|
|
4283
|
-
return await this._invocationContext.artifactService.listArtifactKeys({
|
|
4284
|
-
appName: this._invocationContext.appName,
|
|
4285
|
-
userId: this._invocationContext.userId,
|
|
4286
|
-
sessionId: this._invocationContext.session.id
|
|
4287
|
-
});
|
|
4288
|
-
}
|
|
4289
4292
|
/**
|
|
4290
|
-
*
|
|
4291
|
-
|
|
4292
|
-
|
|
4293
|
-
|
|
4294
|
-
|
|
4295
|
-
|
|
4296
|
-
|
|
4297
|
-
|
|
4298
|
-
|
|
4299
|
-
userId: this._invocationContext.userId
|
|
4300
|
-
});
|
|
4301
|
-
}
|
|
4302
|
-
};
|
|
4303
|
-
|
|
4304
|
-
// src/tools/index.ts
|
|
4305
|
-
init_function_tool();
|
|
4306
|
-
|
|
4307
|
-
// src/tools/function/index.ts
|
|
4308
|
-
init_function_tool();
|
|
4309
|
-
init_function_utils();
|
|
4310
|
-
function createFunctionTool(func, options) {
|
|
4311
|
-
const { FunctionTool: FunctionTool2 } = (init_function_tool(), __toCommonJS(function_tool_exports));
|
|
4312
|
-
return new FunctionTool2(func, options);
|
|
4313
|
-
}
|
|
4314
|
-
|
|
4315
|
-
// src/tools/index.ts
|
|
4316
|
-
init_function_utils();
|
|
4317
|
-
|
|
4318
|
-
// src/tools/common/google-search.ts
|
|
4319
|
-
init_logger();
|
|
4320
|
-
init_base_tool();
|
|
4321
|
-
|
|
4322
|
-
var GoogleSearch = (_class16 = class extends BaseTool {
|
|
4323
|
-
__init26() {this.logger = new Logger({ name: "GoogleSearch" })}
|
|
4324
|
-
/**
|
|
4325
|
-
* Constructor for GoogleSearch
|
|
4326
|
-
*/
|
|
4327
|
-
constructor() {
|
|
4328
|
-
super({
|
|
4329
|
-
name: "google_search",
|
|
4330
|
-
description: "Search the web using Google"
|
|
4331
|
-
});_class16.prototype.__init26.call(this);;
|
|
4293
|
+
* Re-initializes the MCP client when a session is closed.
|
|
4294
|
+
* Used by the retry mechanism.
|
|
4295
|
+
*/
|
|
4296
|
+
async reinitialize() {
|
|
4297
|
+
this.logger.debug("\u{1F504} Reinitializing MCP client after closed connection");
|
|
4298
|
+
await this.cleanupResources();
|
|
4299
|
+
this.client = null;
|
|
4300
|
+
this.transport = null;
|
|
4301
|
+
await this.initialize();
|
|
4332
4302
|
}
|
|
4333
4303
|
/**
|
|
4334
|
-
*
|
|
4304
|
+
* Cleans up resources associated with this client service.
|
|
4305
|
+
* Similar to Python's AsyncExitStack.aclose() functionality.
|
|
4335
4306
|
*/
|
|
4336
|
-
|
|
4337
|
-
|
|
4338
|
-
|
|
4339
|
-
|
|
4340
|
-
|
|
4341
|
-
|
|
4342
|
-
|
|
4343
|
-
query: {
|
|
4344
|
-
type: _genai.Type.STRING,
|
|
4345
|
-
description: "The search query to execute"
|
|
4346
|
-
},
|
|
4347
|
-
num_results: {
|
|
4348
|
-
type: _genai.Type.INTEGER,
|
|
4349
|
-
description: "Number of results to return (max 10)",
|
|
4350
|
-
default: 5
|
|
4307
|
+
async cleanupResources() {
|
|
4308
|
+
try {
|
|
4309
|
+
this.isClosing = true;
|
|
4310
|
+
if (this.client) {
|
|
4311
|
+
try {
|
|
4312
|
+
if (typeof this.client.close === "function") {
|
|
4313
|
+
await this.client.close();
|
|
4351
4314
|
}
|
|
4352
|
-
}
|
|
4353
|
-
|
|
4315
|
+
} catch (err) {
|
|
4316
|
+
}
|
|
4354
4317
|
}
|
|
4355
|
-
|
|
4318
|
+
if (this.transport && typeof this.transport.close === "function") {
|
|
4319
|
+
await this.transport.close();
|
|
4320
|
+
}
|
|
4321
|
+
this.logger.debug("\u{1F9F9} Cleaned up MCP client resources");
|
|
4322
|
+
} catch (error) {
|
|
4323
|
+
this.logger.error("Error cleaning up MCP resources:", error);
|
|
4324
|
+
} finally {
|
|
4325
|
+
this.client = null;
|
|
4326
|
+
this.transport = null;
|
|
4327
|
+
this.isClosing = false;
|
|
4328
|
+
}
|
|
4356
4329
|
}
|
|
4357
4330
|
/**
|
|
4358
|
-
*
|
|
4359
|
-
* This is a simplified implementation that doesn't actually search, just returns mock results
|
|
4331
|
+
* Call an MCP tool with retry capability if the session is closed.
|
|
4360
4332
|
*/
|
|
4361
|
-
async
|
|
4362
|
-
|
|
4363
|
-
|
|
4364
|
-
|
|
4365
|
-
|
|
4366
|
-
|
|
4367
|
-
|
|
4368
|
-
|
|
4369
|
-
|
|
4370
|
-
snippet: `This is a sample result for the query "${args.query}".`
|
|
4333
|
+
async callTool(name, args) {
|
|
4334
|
+
try {
|
|
4335
|
+
const wrappedCall = withRetry(
|
|
4336
|
+
async function() {
|
|
4337
|
+
const client = await this.initialize();
|
|
4338
|
+
return client.callTool({
|
|
4339
|
+
name,
|
|
4340
|
+
arguments: args
|
|
4341
|
+
});
|
|
4371
4342
|
},
|
|
4372
|
-
|
|
4373
|
-
|
|
4374
|
-
|
|
4375
|
-
|
|
4376
|
-
|
|
4377
|
-
|
|
4378
|
-
|
|
4343
|
+
this,
|
|
4344
|
+
async (instance) => await instance.reinitialize(),
|
|
4345
|
+
_optionalChain([this, 'access', _145 => _145.config, 'access', _146 => _146.retryOptions, 'optionalAccess', _147 => _147.maxRetries]) || 2
|
|
4346
|
+
);
|
|
4347
|
+
return await wrappedCall();
|
|
4348
|
+
} catch (error) {
|
|
4349
|
+
if (!(error instanceof McpError)) {
|
|
4350
|
+
throw new McpError(
|
|
4351
|
+
`Error calling tool "${name}": ${error instanceof Error ? error.message : String(error)}`,
|
|
4352
|
+
"tool_execution_error" /* TOOL_EXECUTION_ERROR */,
|
|
4353
|
+
error instanceof Error ? error : void 0
|
|
4354
|
+
);
|
|
4355
|
+
}
|
|
4356
|
+
throw error;
|
|
4357
|
+
}
|
|
4379
4358
|
}
|
|
4380
|
-
|
|
4381
|
-
|
|
4382
|
-
|
|
4383
|
-
|
|
4384
|
-
|
|
4385
|
-
|
|
4386
|
-
|
|
4387
|
-
|
|
4388
|
-
name: "http_request",
|
|
4389
|
-
description: "Make HTTP requests to external APIs and web services"
|
|
4390
|
-
});
|
|
4359
|
+
/**
|
|
4360
|
+
* Closes and cleans up all resources.
|
|
4361
|
+
* Should be called when the service is no longer needed.
|
|
4362
|
+
* Similar to Python's close() method.
|
|
4363
|
+
*/
|
|
4364
|
+
async close() {
|
|
4365
|
+
this.logger.debug("\u{1F51A} Closing MCP client service");
|
|
4366
|
+
await this.cleanupResources();
|
|
4391
4367
|
}
|
|
4392
4368
|
/**
|
|
4393
|
-
*
|
|
4369
|
+
* Checks if the client is currently connected
|
|
4394
4370
|
*/
|
|
4395
|
-
|
|
4396
|
-
return
|
|
4397
|
-
|
|
4398
|
-
|
|
4399
|
-
|
|
4400
|
-
|
|
4401
|
-
|
|
4402
|
-
|
|
4403
|
-
|
|
4404
|
-
|
|
4405
|
-
|
|
4406
|
-
|
|
4407
|
-
|
|
4408
|
-
|
|
4409
|
-
|
|
4410
|
-
|
|
4411
|
-
|
|
4412
|
-
|
|
4413
|
-
|
|
4414
|
-
|
|
4415
|
-
|
|
4416
|
-
|
|
4417
|
-
|
|
4418
|
-
|
|
4419
|
-
|
|
4420
|
-
|
|
4421
|
-
|
|
4422
|
-
|
|
4423
|
-
|
|
4424
|
-
timeout: {
|
|
4425
|
-
type: _genai.Type.INTEGER,
|
|
4426
|
-
description: "Request timeout in milliseconds",
|
|
4427
|
-
default: 1e4
|
|
4371
|
+
isConnected() {
|
|
4372
|
+
return !!this.client && !this.isClosing;
|
|
4373
|
+
}
|
|
4374
|
+
async setupSamplingHandler(client) {
|
|
4375
|
+
if (!this.mcpSamplingHandler) {
|
|
4376
|
+
this.logger.debug(
|
|
4377
|
+
"\u26A0\uFE0F No sampling handler provided - sampling requests will be rejected"
|
|
4378
|
+
);
|
|
4379
|
+
return;
|
|
4380
|
+
}
|
|
4381
|
+
try {
|
|
4382
|
+
client.setRequestHandler(
|
|
4383
|
+
_typesjs.CreateMessageRequestSchema,
|
|
4384
|
+
async (request) => {
|
|
4385
|
+
try {
|
|
4386
|
+
this.logger.debug("Received sampling request:", request);
|
|
4387
|
+
const response = await this.mcpSamplingHandler.handleSamplingRequest(request);
|
|
4388
|
+
this.logger.debug("\u2705 Sampling request completed successfully");
|
|
4389
|
+
return response;
|
|
4390
|
+
} catch (error) {
|
|
4391
|
+
this.logger.error("\u274C Error handling sampling request:", error);
|
|
4392
|
+
if (error instanceof McpError) {
|
|
4393
|
+
throw error;
|
|
4394
|
+
}
|
|
4395
|
+
throw new McpError(
|
|
4396
|
+
`Sampling request failed: ${error instanceof Error ? error.message : String(error)}`,
|
|
4397
|
+
"SAMPLING_ERROR" /* SAMPLING_ERROR */,
|
|
4398
|
+
error instanceof Error ? error : void 0
|
|
4399
|
+
);
|
|
4428
4400
|
}
|
|
4429
|
-
}
|
|
4430
|
-
|
|
4431
|
-
}
|
|
4432
|
-
}
|
|
4401
|
+
}
|
|
4402
|
+
);
|
|
4403
|
+
this.logger.debug("\u{1F3AF} Sampling handler registered successfully");
|
|
4404
|
+
} catch (error) {
|
|
4405
|
+
this.logger.error("Failed to setup sampling handler:", error);
|
|
4406
|
+
this.logger.debug(
|
|
4407
|
+
"\u26A0\uFE0F Sampling handler registration failed, continuing without sampling support"
|
|
4408
|
+
);
|
|
4409
|
+
}
|
|
4433
4410
|
}
|
|
4434
4411
|
/**
|
|
4435
|
-
*
|
|
4412
|
+
* Set a new ADK sampling handler
|
|
4436
4413
|
*/
|
|
4437
|
-
|
|
4438
|
-
|
|
4439
|
-
|
|
4440
|
-
|
|
4441
|
-
|
|
4442
|
-
headers = {},
|
|
4443
|
-
body,
|
|
4444
|
-
params,
|
|
4445
|
-
timeout = 1e4
|
|
4446
|
-
} = args;
|
|
4447
|
-
const urlObj = new URL(url);
|
|
4448
|
-
if (params) {
|
|
4449
|
-
Object.entries(params).forEach(([key, value]) => {
|
|
4450
|
-
urlObj.searchParams.append(key, value);
|
|
4451
|
-
});
|
|
4452
|
-
}
|
|
4453
|
-
const requestHeaders = { ...headers };
|
|
4454
|
-
if (body && !requestHeaders["Content-Type"] && this.isValidJson(body)) {
|
|
4455
|
-
requestHeaders["Content-Type"] = "application/json";
|
|
4456
|
-
}
|
|
4457
|
-
const options = {
|
|
4458
|
-
method,
|
|
4459
|
-
headers: requestHeaders,
|
|
4460
|
-
body,
|
|
4461
|
-
signal: AbortSignal.timeout(timeout)
|
|
4462
|
-
};
|
|
4463
|
-
const response = await fetch(urlObj.toString(), options);
|
|
4464
|
-
const responseHeaders = {};
|
|
4465
|
-
response.headers.forEach((value, key) => {
|
|
4466
|
-
responseHeaders[key] = value;
|
|
4414
|
+
setSamplingHandler(handler) {
|
|
4415
|
+
this.mcpSamplingHandler = new McpSamplingHandler(handler);
|
|
4416
|
+
if (this.client) {
|
|
4417
|
+
this.setupSamplingHandler(this.client).catch((error) => {
|
|
4418
|
+
this.logger.error("Failed to update ADK sampling handler:", error);
|
|
4467
4419
|
});
|
|
4468
|
-
const responseBody = await response.text();
|
|
4469
|
-
return {
|
|
4470
|
-
statusCode: response.status,
|
|
4471
|
-
headers: responseHeaders,
|
|
4472
|
-
body: responseBody
|
|
4473
|
-
};
|
|
4474
|
-
} catch (error) {
|
|
4475
|
-
return {
|
|
4476
|
-
statusCode: 0,
|
|
4477
|
-
headers: {},
|
|
4478
|
-
body: "",
|
|
4479
|
-
error: error instanceof Error ? error.message : String(error)
|
|
4480
|
-
};
|
|
4481
4420
|
}
|
|
4482
4421
|
}
|
|
4483
4422
|
/**
|
|
4484
|
-
*
|
|
4423
|
+
* Remove the sampling handler
|
|
4485
4424
|
*/
|
|
4486
|
-
|
|
4487
|
-
|
|
4488
|
-
|
|
4489
|
-
|
|
4490
|
-
|
|
4491
|
-
|
|
4425
|
+
removeSamplingHandler() {
|
|
4426
|
+
this.mcpSamplingHandler = null;
|
|
4427
|
+
if (this.client) {
|
|
4428
|
+
try {
|
|
4429
|
+
_optionalChain([this, 'access', _148 => _148.client, 'access', _149 => _149.removeRequestHandler, 'optionalCall', _150 => _150("sampling/createMessage")]);
|
|
4430
|
+
} catch (error) {
|
|
4431
|
+
this.logger.error("Failed to remove sampling handler:", error);
|
|
4432
|
+
}
|
|
4492
4433
|
}
|
|
4493
4434
|
}
|
|
4494
|
-
};
|
|
4435
|
+
}, _class14);
|
|
4495
4436
|
|
|
4496
|
-
// src/tools/
|
|
4437
|
+
// src/tools/index.ts
|
|
4497
4438
|
init_base_tool();
|
|
4498
|
-
var _promises = require('fs/promises'); var fs2 = _interopRequireWildcard(_promises);
|
|
4499
|
-
var _path = require('path'); var path2 = _interopRequireWildcard(_path);
|
|
4500
4439
|
|
|
4501
|
-
|
|
4440
|
+
// src/tools/base/create-tool.ts
|
|
4441
|
+
init_base_tool();
|
|
4442
|
+
var _zod = require('zod'); var z = _interopRequireWildcard(_zod);
|
|
4443
|
+
var _zodtojsonschema = require('zod-to-json-schema');
|
|
4444
|
+
var CreatedTool = class extends BaseTool {
|
|
4502
4445
|
|
|
4503
|
-
|
|
4446
|
+
|
|
4447
|
+
|
|
4448
|
+
constructor(config) {
|
|
4504
4449
|
super({
|
|
4505
|
-
name:
|
|
4506
|
-
description:
|
|
4450
|
+
name: config.name,
|
|
4451
|
+
description: config.description,
|
|
4452
|
+
isLongRunning: _nullishCoalesce(config.isLongRunning, () => ( false)),
|
|
4453
|
+
shouldRetryOnFailure: _nullishCoalesce(config.shouldRetryOnFailure, () => ( false)),
|
|
4454
|
+
maxRetryAttempts: _nullishCoalesce(config.maxRetryAttempts, () => ( 3))
|
|
4507
4455
|
});
|
|
4508
|
-
this.
|
|
4509
|
-
|
|
4510
|
-
|
|
4511
|
-
* Get the function declaration for the tool
|
|
4512
|
-
*/
|
|
4513
|
-
getDeclaration() {
|
|
4514
|
-
return {
|
|
4515
|
-
name: this.name,
|
|
4516
|
-
description: this.description,
|
|
4517
|
-
parameters: {
|
|
4518
|
-
type: _genai.Type.OBJECT,
|
|
4519
|
-
properties: {
|
|
4520
|
-
operation: {
|
|
4521
|
-
type: _genai.Type.STRING,
|
|
4522
|
-
description: "The file operation to perform",
|
|
4523
|
-
enum: [
|
|
4524
|
-
"read",
|
|
4525
|
-
"write",
|
|
4526
|
-
"append",
|
|
4527
|
-
"delete",
|
|
4528
|
-
"exists",
|
|
4529
|
-
"list",
|
|
4530
|
-
"mkdir"
|
|
4531
|
-
]
|
|
4532
|
-
},
|
|
4533
|
-
filepath: {
|
|
4534
|
-
type: _genai.Type.STRING,
|
|
4535
|
-
description: "Path to the file or directory (relative to the base path)"
|
|
4536
|
-
},
|
|
4537
|
-
content: {
|
|
4538
|
-
type: _genai.Type.STRING,
|
|
4539
|
-
description: "Content to write to the file (for write and append operations)"
|
|
4540
|
-
},
|
|
4541
|
-
encoding: {
|
|
4542
|
-
type: _genai.Type.STRING,
|
|
4543
|
-
description: "File encoding to use",
|
|
4544
|
-
default: "utf8"
|
|
4545
|
-
}
|
|
4546
|
-
},
|
|
4547
|
-
required: ["operation", "filepath"]
|
|
4548
|
-
}
|
|
4549
|
-
};
|
|
4456
|
+
this.func = config.fn;
|
|
4457
|
+
this.schema = _nullishCoalesce(config.schema, () => ( z.object({})));
|
|
4458
|
+
this.functionDeclaration = this.buildDeclaration();
|
|
4550
4459
|
}
|
|
4551
4460
|
/**
|
|
4552
|
-
*
|
|
4461
|
+
* Executes the tool function with validation
|
|
4553
4462
|
*/
|
|
4554
|
-
async runAsync(args,
|
|
4463
|
+
async runAsync(args, context4) {
|
|
4555
4464
|
try {
|
|
4556
|
-
const
|
|
4557
|
-
this.
|
|
4558
|
-
|
|
4559
|
-
switch (args.operation) {
|
|
4560
|
-
case "read":
|
|
4561
|
-
return await this.readFile(resolvedPath, encoding);
|
|
4562
|
-
case "write":
|
|
4563
|
-
return await this.writeFile(
|
|
4564
|
-
resolvedPath,
|
|
4565
|
-
args.content || "",
|
|
4566
|
-
encoding
|
|
4567
|
-
);
|
|
4568
|
-
case "append":
|
|
4569
|
-
return await this.appendFile(
|
|
4570
|
-
resolvedPath,
|
|
4571
|
-
args.content || "",
|
|
4572
|
-
encoding
|
|
4573
|
-
);
|
|
4574
|
-
case "delete":
|
|
4575
|
-
return await this.deleteFile(resolvedPath);
|
|
4576
|
-
case "exists":
|
|
4577
|
-
return await this.fileExists(resolvedPath);
|
|
4578
|
-
case "list":
|
|
4579
|
-
return await this.listDirectory(resolvedPath);
|
|
4580
|
-
case "mkdir":
|
|
4581
|
-
return await this.makeDirectory(resolvedPath);
|
|
4582
|
-
default:
|
|
4583
|
-
throw new Error(`Unsupported operation: ${args.operation}`);
|
|
4584
|
-
}
|
|
4465
|
+
const validatedArgs = this.schema.parse(args);
|
|
4466
|
+
const result = await Promise.resolve(this.func(validatedArgs, context4));
|
|
4467
|
+
return _nullishCoalesce(result, () => ( {}));
|
|
4585
4468
|
} catch (error) {
|
|
4469
|
+
if (error instanceof z.ZodError) {
|
|
4470
|
+
return {
|
|
4471
|
+
error: `Invalid arguments for ${this.name}: ${error.message}`
|
|
4472
|
+
};
|
|
4473
|
+
}
|
|
4586
4474
|
return {
|
|
4587
|
-
|
|
4588
|
-
error: error instanceof Error ? error.message : String(error)
|
|
4475
|
+
error: `Error executing ${this.name}: ${error instanceof Error ? error.message : String(error)}`
|
|
4589
4476
|
};
|
|
4590
4477
|
}
|
|
4591
4478
|
}
|
|
4592
4479
|
/**
|
|
4593
|
-
*
|
|
4480
|
+
* Returns the function declaration for this tool
|
|
4594
4481
|
*/
|
|
4595
|
-
|
|
4596
|
-
return
|
|
4482
|
+
getDeclaration() {
|
|
4483
|
+
return this.functionDeclaration;
|
|
4597
4484
|
}
|
|
4598
4485
|
/**
|
|
4599
|
-
*
|
|
4486
|
+
* Builds the function declaration from the Zod schema
|
|
4600
4487
|
*/
|
|
4601
|
-
|
|
4602
|
-
const
|
|
4603
|
-
|
|
4604
|
-
|
|
4605
|
-
|
|
4606
|
-
|
|
4607
|
-
|
|
4608
|
-
|
|
4488
|
+
buildDeclaration() {
|
|
4489
|
+
const rawParameters = _zodtojsonschema.zodToJsonSchema.call(void 0, this.schema, {
|
|
4490
|
+
target: "jsonSchema7",
|
|
4491
|
+
$refStrategy: "none"
|
|
4492
|
+
});
|
|
4493
|
+
const { $schema, ...parameters } = rawParameters;
|
|
4494
|
+
return {
|
|
4495
|
+
name: this.name,
|
|
4496
|
+
description: this.description,
|
|
4497
|
+
parameters
|
|
4498
|
+
};
|
|
4499
|
+
}
|
|
4500
|
+
};
|
|
4501
|
+
function createTool(config) {
|
|
4502
|
+
return new CreatedTool(config);
|
|
4503
|
+
}
|
|
4504
|
+
|
|
4505
|
+
// src/tools/common/agent-tool.ts
|
|
4506
|
+
init_logger();
|
|
4507
|
+
|
|
4508
|
+
|
|
4509
|
+
|
|
4510
|
+
// src/agents/invocation-context.ts
|
|
4511
|
+
var LlmCallsLimitExceededError = class extends Error {
|
|
4512
|
+
constructor(message) {
|
|
4513
|
+
super(message);
|
|
4514
|
+
this.name = "LlmCallsLimitExceededError";
|
|
4609
4515
|
}
|
|
4516
|
+
};
|
|
4517
|
+
var InvocationCostManager = (_class15 = class {constructor() { _class15.prototype.__init28.call(this); }
|
|
4610
4518
|
/**
|
|
4611
|
-
*
|
|
4519
|
+
* A counter that keeps track of number of llm calls made.
|
|
4612
4520
|
*/
|
|
4613
|
-
|
|
4614
|
-
try {
|
|
4615
|
-
const content = await fs2.default.readFile(filepath, { encoding });
|
|
4616
|
-
return {
|
|
4617
|
-
success: true,
|
|
4618
|
-
data: content
|
|
4619
|
-
};
|
|
4620
|
-
} catch (error) {
|
|
4621
|
-
return {
|
|
4622
|
-
success: false,
|
|
4623
|
-
error: `Failed to read file: ${error instanceof Error ? error.message : String(error)}`
|
|
4624
|
-
};
|
|
4625
|
-
}
|
|
4626
|
-
}
|
|
4521
|
+
__init28() {this._numberOfLlmCalls = 0}
|
|
4627
4522
|
/**
|
|
4628
|
-
*
|
|
4523
|
+
* Increments _numberOfLlmCalls and enforces the limit.
|
|
4629
4524
|
*/
|
|
4630
|
-
|
|
4631
|
-
|
|
4632
|
-
|
|
4633
|
-
|
|
4634
|
-
|
|
4635
|
-
|
|
4636
|
-
success: true
|
|
4637
|
-
};
|
|
4638
|
-
} catch (error) {
|
|
4639
|
-
return {
|
|
4640
|
-
success: false,
|
|
4641
|
-
error: `Failed to write to file: ${error instanceof Error ? error.message : String(error)}`
|
|
4642
|
-
};
|
|
4525
|
+
incrementAndEnforceLlmCallsLimit(runConfig) {
|
|
4526
|
+
this._numberOfLlmCalls += 1;
|
|
4527
|
+
if (runConfig && runConfig.maxLlmCalls > 0 && this._numberOfLlmCalls > runConfig.maxLlmCalls) {
|
|
4528
|
+
throw new LlmCallsLimitExceededError(
|
|
4529
|
+
`Max number of llm calls limit of \`${runConfig.maxLlmCalls}\` exceeded`
|
|
4530
|
+
);
|
|
4643
4531
|
}
|
|
4644
4532
|
}
|
|
4533
|
+
}, _class15);
|
|
4534
|
+
function newInvocationContextId() {
|
|
4535
|
+
return `e-${crypto.randomUUID()}`;
|
|
4536
|
+
}
|
|
4537
|
+
var InvocationContext = (_class16 = class _InvocationContext {
|
|
4538
|
+
|
|
4539
|
+
|
|
4540
|
+
|
|
4645
4541
|
/**
|
|
4646
|
-
*
|
|
4542
|
+
* The id of this invocation context. Readonly.
|
|
4647
4543
|
*/
|
|
4648
|
-
|
|
4649
|
-
|
|
4650
|
-
|
|
4651
|
-
|
|
4652
|
-
|
|
4653
|
-
|
|
4654
|
-
|
|
4655
|
-
|
|
4656
|
-
|
|
4657
|
-
|
|
4658
|
-
|
|
4659
|
-
|
|
4660
|
-
|
|
4661
|
-
|
|
4544
|
+
|
|
4545
|
+
/**
|
|
4546
|
+
* The branch of the invocation context.
|
|
4547
|
+
*
|
|
4548
|
+
* The format is like agent_1.agent_2.agent_3, where agent_1 is the parent of
|
|
4549
|
+
* agent_2, and agent_2 is the parent of agent_3.
|
|
4550
|
+
*
|
|
4551
|
+
* Branch is used when multiple sub-agents shouldn't see their peer agents'
|
|
4552
|
+
* conversation history.
|
|
4553
|
+
*/
|
|
4554
|
+
|
|
4555
|
+
/**
|
|
4556
|
+
* The current agent of this invocation context. Readonly.
|
|
4557
|
+
*/
|
|
4558
|
+
|
|
4559
|
+
/**
|
|
4560
|
+
* The user content that started this invocation. Readonly.
|
|
4561
|
+
*/
|
|
4562
|
+
|
|
4563
|
+
/**
|
|
4564
|
+
* The current session of this invocation context. Readonly.
|
|
4565
|
+
*/
|
|
4566
|
+
|
|
4567
|
+
/**
|
|
4568
|
+
* Whether to end this invocation.
|
|
4569
|
+
*
|
|
4570
|
+
* Set to True in callbacks or tools to terminate this invocation.
|
|
4571
|
+
*/
|
|
4572
|
+
__init29() {this.endInvocation = false}
|
|
4573
|
+
/**
|
|
4574
|
+
* The queue to receive live requests.
|
|
4575
|
+
*/
|
|
4576
|
+
|
|
4577
|
+
/**
|
|
4578
|
+
* The running streaming tools of this invocation.
|
|
4579
|
+
*/
|
|
4580
|
+
|
|
4581
|
+
/**
|
|
4582
|
+
* Caches necessary, data audio or contents, that are needed by transcription.
|
|
4583
|
+
*/
|
|
4584
|
+
|
|
4585
|
+
/**
|
|
4586
|
+
* Configurations for live agents under this invocation.
|
|
4587
|
+
*/
|
|
4588
|
+
|
|
4589
|
+
/**
|
|
4590
|
+
* A container to keep track of different kinds of costs incurred as a part
|
|
4591
|
+
* of this invocation.
|
|
4592
|
+
*/
|
|
4593
|
+
__init30() {this._invocationCostManager = new InvocationCostManager()}
|
|
4594
|
+
/**
|
|
4595
|
+
* Constructor for InvocationContext
|
|
4596
|
+
*/
|
|
4597
|
+
constructor(options) {;_class16.prototype.__init29.call(this);_class16.prototype.__init30.call(this);
|
|
4598
|
+
this.artifactService = options.artifactService;
|
|
4599
|
+
this.sessionService = options.sessionService;
|
|
4600
|
+
this.memoryService = options.memoryService;
|
|
4601
|
+
this.invocationId = options.invocationId || newInvocationContextId();
|
|
4602
|
+
this.branch = options.branch;
|
|
4603
|
+
this.agent = options.agent;
|
|
4604
|
+
this.userContent = options.userContent;
|
|
4605
|
+
this.session = options.session;
|
|
4606
|
+
this.endInvocation = options.endInvocation || false;
|
|
4607
|
+
this.liveRequestQueue = options.liveRequestQueue;
|
|
4608
|
+
this.activeStreamingTools = options.activeStreamingTools;
|
|
4609
|
+
this.transcriptionCache = options.transcriptionCache;
|
|
4610
|
+
this.runConfig = options.runConfig;
|
|
4662
4611
|
}
|
|
4663
4612
|
/**
|
|
4664
|
-
*
|
|
4613
|
+
* App name from the session
|
|
4665
4614
|
*/
|
|
4666
|
-
|
|
4667
|
-
|
|
4668
|
-
await fs2.default.unlink(filepath);
|
|
4669
|
-
return {
|
|
4670
|
-
success: true
|
|
4671
|
-
};
|
|
4672
|
-
} catch (error) {
|
|
4673
|
-
return {
|
|
4674
|
-
success: false,
|
|
4675
|
-
error: `Failed to delete file: ${error instanceof Error ? error.message : String(error)}`
|
|
4676
|
-
};
|
|
4677
|
-
}
|
|
4615
|
+
get appName() {
|
|
4616
|
+
return this.session.appName;
|
|
4678
4617
|
}
|
|
4679
4618
|
/**
|
|
4680
|
-
*
|
|
4619
|
+
* User ID from the session
|
|
4681
4620
|
*/
|
|
4682
|
-
|
|
4683
|
-
|
|
4684
|
-
await fs2.default.access(filepath);
|
|
4685
|
-
return {
|
|
4686
|
-
success: true,
|
|
4687
|
-
data: true
|
|
4688
|
-
};
|
|
4689
|
-
} catch (e3) {
|
|
4690
|
-
return {
|
|
4691
|
-
success: true,
|
|
4692
|
-
data: false
|
|
4693
|
-
};
|
|
4694
|
-
}
|
|
4621
|
+
get userId() {
|
|
4622
|
+
return this.session.userId;
|
|
4695
4623
|
}
|
|
4696
4624
|
/**
|
|
4697
|
-
*
|
|
4625
|
+
* Tracks number of llm calls made.
|
|
4626
|
+
*
|
|
4627
|
+
* @throws {LlmCallsLimitExceededError} If number of llm calls made exceed the set threshold.
|
|
4698
4628
|
*/
|
|
4699
|
-
|
|
4700
|
-
|
|
4701
|
-
|
|
4702
|
-
|
|
4703
|
-
entries.map(async (entry) => {
|
|
4704
|
-
const entryPath = path2.default.join(dirpath, entry.name);
|
|
4705
|
-
const stats = await fs2.default.stat(entryPath);
|
|
4706
|
-
return {
|
|
4707
|
-
name: entry.name,
|
|
4708
|
-
path: entryPath,
|
|
4709
|
-
isFile: entry.isFile(),
|
|
4710
|
-
isDirectory: entry.isDirectory(),
|
|
4711
|
-
size: stats.size,
|
|
4712
|
-
created: stats.birthtime,
|
|
4713
|
-
modified: stats.mtime
|
|
4714
|
-
};
|
|
4715
|
-
})
|
|
4716
|
-
);
|
|
4717
|
-
return {
|
|
4718
|
-
success: true,
|
|
4719
|
-
data: results
|
|
4720
|
-
};
|
|
4721
|
-
} catch (error) {
|
|
4722
|
-
return {
|
|
4723
|
-
success: false,
|
|
4724
|
-
error: `Failed to list directory: ${error instanceof Error ? error.message : String(error)}`
|
|
4725
|
-
};
|
|
4726
|
-
}
|
|
4629
|
+
incrementLlmCallCount() {
|
|
4630
|
+
this._invocationCostManager.incrementAndEnforceLlmCallsLimit(
|
|
4631
|
+
this.runConfig
|
|
4632
|
+
);
|
|
4727
4633
|
}
|
|
4728
4634
|
/**
|
|
4729
|
-
*
|
|
4635
|
+
* Creates a child invocation context for a sub-agent
|
|
4730
4636
|
*/
|
|
4731
|
-
|
|
4732
|
-
|
|
4733
|
-
|
|
4734
|
-
|
|
4735
|
-
|
|
4736
|
-
|
|
4737
|
-
|
|
4738
|
-
|
|
4739
|
-
|
|
4740
|
-
|
|
4741
|
-
|
|
4742
|
-
|
|
4637
|
+
createChildContext(agent) {
|
|
4638
|
+
return new _InvocationContext({
|
|
4639
|
+
artifactService: this.artifactService,
|
|
4640
|
+
sessionService: this.sessionService,
|
|
4641
|
+
memoryService: this.memoryService,
|
|
4642
|
+
invocationId: this.invocationId,
|
|
4643
|
+
// Keep same invocation ID
|
|
4644
|
+
branch: this.branch ? `${this.branch}.${agent.name}` : agent.name,
|
|
4645
|
+
// Update branch
|
|
4646
|
+
agent,
|
|
4647
|
+
// Update to the new agent
|
|
4648
|
+
userContent: this.userContent,
|
|
4649
|
+
session: this.session,
|
|
4650
|
+
endInvocation: this.endInvocation,
|
|
4651
|
+
liveRequestQueue: this.liveRequestQueue,
|
|
4652
|
+
activeStreamingTools: this.activeStreamingTools,
|
|
4653
|
+
transcriptionCache: this.transcriptionCache,
|
|
4654
|
+
runConfig: this.runConfig
|
|
4655
|
+
});
|
|
4743
4656
|
}
|
|
4744
|
-
};
|
|
4657
|
+
}, _class16);
|
|
4745
4658
|
|
|
4746
|
-
// src/tools/common/
|
|
4659
|
+
// src/tools/common/agent-tool.ts
|
|
4747
4660
|
init_base_tool();
|
|
4748
|
-
|
|
4749
|
-
|
|
4750
|
-
|
|
4661
|
+
function isLlmAgent(agent) {
|
|
4662
|
+
return true;
|
|
4663
|
+
}
|
|
4664
|
+
var AgentTool = (_class17 = class extends BaseTool {
|
|
4665
|
+
/**
|
|
4666
|
+
* The agent used by this tool
|
|
4667
|
+
*/
|
|
4668
|
+
|
|
4669
|
+
/**
|
|
4670
|
+
* The function declaration schema
|
|
4671
|
+
*/
|
|
4672
|
+
|
|
4673
|
+
/**
|
|
4674
|
+
* The key to store the tool output in the state
|
|
4675
|
+
*/
|
|
4676
|
+
|
|
4677
|
+
/**
|
|
4678
|
+
* Whether to skip summarization of the agent's response
|
|
4679
|
+
*/
|
|
4680
|
+
|
|
4681
|
+
__init31() {this.logger = new Logger({ name: "AgentTool" })}
|
|
4682
|
+
/**
|
|
4683
|
+
* Create a new agent tool
|
|
4684
|
+
*/
|
|
4685
|
+
constructor(config) {
|
|
4751
4686
|
super({
|
|
4752
|
-
name:
|
|
4753
|
-
description:
|
|
4754
|
-
isLongRunning:
|
|
4755
|
-
|
|
4687
|
+
name: config.name,
|
|
4688
|
+
description: config.description || config.agent.description,
|
|
4689
|
+
isLongRunning: config.isLongRunning || false,
|
|
4690
|
+
shouldRetryOnFailure: config.shouldRetryOnFailure || false,
|
|
4691
|
+
maxRetryAttempts: config.maxRetryAttempts || 3
|
|
4692
|
+
});_class17.prototype.__init31.call(this);;
|
|
4693
|
+
this.agent = config.agent;
|
|
4694
|
+
this.functionDeclaration = config.functionDeclaration;
|
|
4695
|
+
this.outputKey = config.outputKey;
|
|
4696
|
+
this.skipSummarization = config.skipSummarization || false;
|
|
4756
4697
|
}
|
|
4757
4698
|
/**
|
|
4758
4699
|
* Get the function declaration for the tool
|
|
4759
4700
|
*/
|
|
4760
4701
|
getDeclaration() {
|
|
4702
|
+
if (this.functionDeclaration) {
|
|
4703
|
+
return this.functionDeclaration;
|
|
4704
|
+
}
|
|
4705
|
+
const description = isLlmAgent(this.agent) ? typeof this.agent.instruction === "string" ? this.agent.instruction : this.description : this.description;
|
|
4761
4706
|
return {
|
|
4762
4707
|
name: this.name,
|
|
4763
|
-
description
|
|
4708
|
+
description,
|
|
4764
4709
|
parameters: {
|
|
4765
4710
|
type: _genai.Type.OBJECT,
|
|
4766
4711
|
properties: {
|
|
4767
|
-
|
|
4768
|
-
type: _genai.Type.STRING,
|
|
4769
|
-
description: "The prompt message to display to the user"
|
|
4770
|
-
},
|
|
4771
|
-
options: {
|
|
4772
|
-
type: _genai.Type.ARRAY,
|
|
4773
|
-
description: "Optional array of choices to present to the user",
|
|
4774
|
-
items: {
|
|
4775
|
-
type: _genai.Type.STRING
|
|
4776
|
-
}
|
|
4777
|
-
},
|
|
4778
|
-
defaultValue: {
|
|
4712
|
+
input: {
|
|
4779
4713
|
type: _genai.Type.STRING,
|
|
4780
|
-
description: "
|
|
4714
|
+
description: "The input to provide to the agent"
|
|
4781
4715
|
}
|
|
4782
4716
|
},
|
|
4783
|
-
required: ["
|
|
4717
|
+
required: ["input"]
|
|
4784
4718
|
}
|
|
4785
4719
|
};
|
|
4786
4720
|
}
|
|
4787
4721
|
/**
|
|
4788
|
-
* Execute the
|
|
4722
|
+
* Execute the tool by running the agent with the provided input
|
|
4789
4723
|
*/
|
|
4790
|
-
async runAsync(
|
|
4724
|
+
async runAsync(params, context4) {
|
|
4791
4725
|
try {
|
|
4792
|
-
const
|
|
4793
|
-
if (!
|
|
4794
|
-
|
|
4795
|
-
|
|
4796
|
-
|
|
4797
|
-
};
|
|
4798
|
-
}
|
|
4799
|
-
if (actions.skipSummarization) {
|
|
4800
|
-
actions.skipSummarization(true);
|
|
4726
|
+
const input = params.input || Object.values(params)[0];
|
|
4727
|
+
if (!isLlmAgent(this.agent)) {
|
|
4728
|
+
throw new Error(
|
|
4729
|
+
`Agent ${this.name} does not support running as a tool`
|
|
4730
|
+
);
|
|
4801
4731
|
}
|
|
4802
|
-
const
|
|
4803
|
-
|
|
4804
|
-
|
|
4805
|
-
|
|
4806
|
-
|
|
4807
|
-
|
|
4808
|
-
|
|
4732
|
+
const parentInvocation = context4._invocationContext;
|
|
4733
|
+
const childInvocationContext = new InvocationContext({
|
|
4734
|
+
invocationId: _uuid.v4.call(void 0, ),
|
|
4735
|
+
agent: this.agent,
|
|
4736
|
+
session: parentInvocation.session,
|
|
4737
|
+
artifactService: parentInvocation.artifactService,
|
|
4738
|
+
sessionService: parentInvocation.sessionService,
|
|
4739
|
+
memoryService: parentInvocation.memoryService,
|
|
4740
|
+
runConfig: parentInvocation.runConfig,
|
|
4741
|
+
userContent: {
|
|
4742
|
+
role: "user",
|
|
4743
|
+
parts: [{ text: String(input) }]
|
|
4744
|
+
},
|
|
4745
|
+
branch: parentInvocation.branch ? `${parentInvocation.branch}.${this.agent.name}` : this.agent.name
|
|
4809
4746
|
});
|
|
4810
|
-
|
|
4811
|
-
|
|
4812
|
-
|
|
4813
|
-
|
|
4747
|
+
let lastEvent = null;
|
|
4748
|
+
for await (const event of this.agent.runAsync(childInvocationContext)) {
|
|
4749
|
+
if (!event.partial) {
|
|
4750
|
+
await childInvocationContext.sessionService.appendEvent(
|
|
4751
|
+
childInvocationContext.session,
|
|
4752
|
+
event
|
|
4753
|
+
);
|
|
4754
|
+
}
|
|
4755
|
+
if (event.content && event.author === this.agent.name) {
|
|
4756
|
+
lastEvent = event;
|
|
4757
|
+
}
|
|
4758
|
+
}
|
|
4759
|
+
if (!lastEvent || !lastEvent.content || !lastEvent.content.parts) {
|
|
4760
|
+
return "";
|
|
4761
|
+
}
|
|
4762
|
+
const mergedText = lastEvent.content.parts.filter((part) => part.text !== void 0 && part.text !== null).map((part) => part.text).join("\n");
|
|
4763
|
+
let toolResult;
|
|
4764
|
+
try {
|
|
4765
|
+
toolResult = JSON.parse(mergedText);
|
|
4766
|
+
} catch (e2) {
|
|
4767
|
+
toolResult = mergedText;
|
|
4768
|
+
}
|
|
4769
|
+
if (this.outputKey && _optionalChain([context4, 'optionalAccess', _151 => _151.state])) {
|
|
4770
|
+
context4.state[this.outputKey] = toolResult;
|
|
4771
|
+
}
|
|
4772
|
+
return toolResult;
|
|
4814
4773
|
} catch (error) {
|
|
4815
|
-
|
|
4816
|
-
|
|
4817
|
-
|
|
4818
|
-
|
|
4774
|
+
this.logger.error(`Error executing agent tool ${this.name}:`, error);
|
|
4775
|
+
throw new Error(
|
|
4776
|
+
`Agent tool execution failed: ${error instanceof Error ? error.message : String(error)}`
|
|
4777
|
+
);
|
|
4819
4778
|
}
|
|
4820
4779
|
}
|
|
4821
|
-
};
|
|
4780
|
+
}, _class17);
|
|
4822
4781
|
|
|
4823
|
-
// src/tools/
|
|
4824
|
-
|
|
4825
|
-
init_base_tool();
|
|
4826
|
-
var ExitLoopTool = (_class17 = class extends BaseTool {
|
|
4827
|
-
__init27() {this.logger = new Logger({ name: "ExitLoopTool" })}
|
|
4782
|
+
// src/tools/tool-context.ts
|
|
4783
|
+
var ToolContext = class extends CallbackContext {
|
|
4828
4784
|
/**
|
|
4829
|
-
*
|
|
4785
|
+
* The function call id of the current tool call. This id was
|
|
4786
|
+
* returned in the function call event from LLM to identify a function call.
|
|
4787
|
+
* If LLM didn't return this id, ADK will assign one to it. This id is used
|
|
4788
|
+
* to map function call response to the original function call.
|
|
4830
4789
|
*/
|
|
4831
|
-
|
|
4832
|
-
super({
|
|
4833
|
-
name: "exit_loop",
|
|
4834
|
-
description: "Exits the loop. Call this function only when you are instructed to do so."
|
|
4835
|
-
});_class17.prototype.__init27.call(this);;
|
|
4836
|
-
}
|
|
4790
|
+
|
|
4837
4791
|
/**
|
|
4838
|
-
*
|
|
4792
|
+
* Constructor for ToolContext
|
|
4839
4793
|
*/
|
|
4840
|
-
|
|
4841
|
-
|
|
4842
|
-
|
|
4794
|
+
constructor(invocationContext, options = {}) {
|
|
4795
|
+
super(invocationContext, { eventActions: options.eventActions });
|
|
4796
|
+
this.functionCallId = options.functionCallId;
|
|
4843
4797
|
}
|
|
4844
|
-
}, _class17);
|
|
4845
|
-
|
|
4846
|
-
// src/tools/common/get-user-choice-tool.ts
|
|
4847
|
-
init_logger();
|
|
4848
|
-
init_base_tool();
|
|
4849
|
-
|
|
4850
|
-
var GetUserChoiceTool = (_class18 = class extends BaseTool {
|
|
4851
|
-
__init28() {this.logger = new Logger({ name: "GetUserChoiceTool" })}
|
|
4852
4798
|
/**
|
|
4853
|
-
*
|
|
4799
|
+
* Gets the event actions of the current tool call
|
|
4854
4800
|
*/
|
|
4855
|
-
|
|
4856
|
-
|
|
4857
|
-
name: "get_user_choice",
|
|
4858
|
-
description: "This tool provides the options to the user and asks them to choose one. Use this tool when you need the user to make a selection between multiple options. Do not list options in your response - use this tool instead.",
|
|
4859
|
-
isLongRunning: true
|
|
4860
|
-
});_class18.prototype.__init28.call(this);;
|
|
4801
|
+
get actions() {
|
|
4802
|
+
return this.eventActions;
|
|
4861
4803
|
}
|
|
4862
4804
|
/**
|
|
4863
|
-
*
|
|
4805
|
+
* Lists the filenames of the artifacts attached to the current session
|
|
4864
4806
|
*/
|
|
4865
|
-
|
|
4866
|
-
|
|
4867
|
-
|
|
4868
|
-
|
|
4869
|
-
|
|
4870
|
-
|
|
4871
|
-
|
|
4872
|
-
|
|
4873
|
-
|
|
4874
|
-
description: "List of options for the user to choose from",
|
|
4875
|
-
items: {
|
|
4876
|
-
type: _genai.Type.STRING
|
|
4877
|
-
}
|
|
4878
|
-
},
|
|
4879
|
-
question: {
|
|
4880
|
-
type: _genai.Type.STRING,
|
|
4881
|
-
description: "The question or prompt to show the user before presenting options"
|
|
4882
|
-
}
|
|
4883
|
-
},
|
|
4884
|
-
required: ["options"]
|
|
4885
|
-
}
|
|
4886
|
-
};
|
|
4807
|
+
async listArtifacts() {
|
|
4808
|
+
if (!this._invocationContext.artifactService) {
|
|
4809
|
+
throw new Error("Artifact service is not initialized.");
|
|
4810
|
+
}
|
|
4811
|
+
return await this._invocationContext.artifactService.listArtifactKeys({
|
|
4812
|
+
appName: this._invocationContext.appName,
|
|
4813
|
+
userId: this._invocationContext.userId,
|
|
4814
|
+
sessionId: this._invocationContext.session.id
|
|
4815
|
+
});
|
|
4887
4816
|
}
|
|
4888
4817
|
/**
|
|
4889
|
-
*
|
|
4890
|
-
* This is a long running operation that will return null initially
|
|
4891
|
-
* and the actual choice will be provided asynchronously
|
|
4818
|
+
* Searches the memory of the current user
|
|
4892
4819
|
*/
|
|
4893
|
-
async
|
|
4894
|
-
this.
|
|
4895
|
-
|
|
4896
|
-
);
|
|
4897
|
-
if (args.question) {
|
|
4898
|
-
this.logger.debug(`Question: ${args.question}`);
|
|
4820
|
+
async searchMemory(query) {
|
|
4821
|
+
if (!this._invocationContext.memoryService) {
|
|
4822
|
+
throw new Error("Memory service is not available.");
|
|
4899
4823
|
}
|
|
4900
|
-
|
|
4901
|
-
|
|
4824
|
+
return await this._invocationContext.memoryService.searchMemory({
|
|
4825
|
+
query,
|
|
4826
|
+
appName: this._invocationContext.appName,
|
|
4827
|
+
userId: this._invocationContext.userId
|
|
4828
|
+
});
|
|
4902
4829
|
}
|
|
4903
|
-
}
|
|
4830
|
+
};
|
|
4904
4831
|
|
|
4905
|
-
// src/tools/
|
|
4832
|
+
// src/tools/index.ts
|
|
4833
|
+
init_function_tool();
|
|
4834
|
+
|
|
4835
|
+
// src/tools/function/index.ts
|
|
4836
|
+
init_function_tool();
|
|
4837
|
+
init_function_utils();
|
|
4838
|
+
function createFunctionTool(func, options) {
|
|
4839
|
+
const { FunctionTool: FunctionTool2 } = (init_function_tool(), __toCommonJS(function_tool_exports));
|
|
4840
|
+
return new FunctionTool2(func, options);
|
|
4841
|
+
}
|
|
4842
|
+
|
|
4843
|
+
// src/tools/index.ts
|
|
4844
|
+
init_function_utils();
|
|
4845
|
+
|
|
4846
|
+
// src/tools/common/google-search.ts
|
|
4906
4847
|
init_logger();
|
|
4907
4848
|
init_base_tool();
|
|
4908
4849
|
|
|
4909
|
-
var
|
|
4910
|
-
|
|
4850
|
+
var GoogleSearch = (_class18 = class extends BaseTool {
|
|
4851
|
+
__init32() {this.logger = new Logger({ name: "GoogleSearch" })}
|
|
4911
4852
|
/**
|
|
4912
|
-
* Constructor for
|
|
4853
|
+
* Constructor for GoogleSearch
|
|
4913
4854
|
*/
|
|
4914
4855
|
constructor() {
|
|
4915
4856
|
super({
|
|
4916
|
-
name: "
|
|
4917
|
-
description: "
|
|
4918
|
-
});
|
|
4857
|
+
name: "google_search",
|
|
4858
|
+
description: "Search the web using Google"
|
|
4859
|
+
});_class18.prototype.__init32.call(this);;
|
|
4919
4860
|
}
|
|
4920
4861
|
/**
|
|
4921
4862
|
* Get the function declaration for the tool
|
|
@@ -4927,38 +4868,54 @@ var TransferToAgentTool = (_class19 = class extends BaseTool {
|
|
|
4927
4868
|
parameters: {
|
|
4928
4869
|
type: _genai.Type.OBJECT,
|
|
4929
4870
|
properties: {
|
|
4930
|
-
|
|
4871
|
+
query: {
|
|
4931
4872
|
type: _genai.Type.STRING,
|
|
4932
|
-
description: "The
|
|
4873
|
+
description: "The search query to execute"
|
|
4874
|
+
},
|
|
4875
|
+
num_results: {
|
|
4876
|
+
type: _genai.Type.INTEGER,
|
|
4877
|
+
description: "Number of results to return (max 10)",
|
|
4878
|
+
default: 5
|
|
4933
4879
|
}
|
|
4934
4880
|
},
|
|
4935
|
-
required: ["
|
|
4881
|
+
required: ["query"]
|
|
4936
4882
|
}
|
|
4937
4883
|
};
|
|
4938
4884
|
}
|
|
4939
4885
|
/**
|
|
4940
|
-
* Execute the
|
|
4886
|
+
* Execute the search
|
|
4887
|
+
* This is a simplified implementation that doesn't actually search, just returns mock results
|
|
4941
4888
|
*/
|
|
4942
|
-
async runAsync(args,
|
|
4943
|
-
this.logger.debug(
|
|
4944
|
-
|
|
4889
|
+
async runAsync(args, _context) {
|
|
4890
|
+
this.logger.debug(
|
|
4891
|
+
`[GoogleSearch] Executing Google search for: ${args.query}`
|
|
4892
|
+
);
|
|
4893
|
+
return {
|
|
4894
|
+
results: [
|
|
4895
|
+
{
|
|
4896
|
+
title: `Result 1 for ${args.query}`,
|
|
4897
|
+
link: "https://example.com/1",
|
|
4898
|
+
snippet: `This is a sample result for the query "${args.query}".`
|
|
4899
|
+
},
|
|
4900
|
+
{
|
|
4901
|
+
title: `Result 2 for ${args.query}`,
|
|
4902
|
+
link: "https://example.com/2",
|
|
4903
|
+
snippet: `Another sample result for "${args.query}".`
|
|
4904
|
+
}
|
|
4905
|
+
]
|
|
4906
|
+
};
|
|
4945
4907
|
}
|
|
4946
|
-
},
|
|
4908
|
+
}, _class18);
|
|
4947
4909
|
|
|
4948
|
-
// src/tools/common/
|
|
4949
|
-
init_logger();
|
|
4910
|
+
// src/tools/common/http-request-tool.ts
|
|
4950
4911
|
init_base_tool();
|
|
4951
4912
|
|
|
4952
|
-
var
|
|
4953
|
-
__init30() {this.logger = new Logger({ name: "LoadMemoryTool" })}
|
|
4954
|
-
/**
|
|
4955
|
-
* Constructor for LoadMemoryTool
|
|
4956
|
-
*/
|
|
4913
|
+
var HttpRequestTool = class extends BaseTool {
|
|
4957
4914
|
constructor() {
|
|
4958
4915
|
super({
|
|
4959
|
-
name: "
|
|
4960
|
-
description: "
|
|
4961
|
-
});
|
|
4916
|
+
name: "http_request",
|
|
4917
|
+
description: "Make HTTP requests to external APIs and web services"
|
|
4918
|
+
});
|
|
4962
4919
|
}
|
|
4963
4920
|
/**
|
|
4964
4921
|
* Get the function declaration for the tool
|
|
@@ -4970,45 +4927,113 @@ var LoadMemoryTool = (_class20 = class extends BaseTool {
|
|
|
4970
4927
|
parameters: {
|
|
4971
4928
|
type: _genai.Type.OBJECT,
|
|
4972
4929
|
properties: {
|
|
4973
|
-
|
|
4930
|
+
url: {
|
|
4974
4931
|
type: _genai.Type.STRING,
|
|
4975
|
-
description: "The
|
|
4932
|
+
description: "The URL to send the request to"
|
|
4933
|
+
},
|
|
4934
|
+
method: {
|
|
4935
|
+
type: _genai.Type.STRING,
|
|
4936
|
+
description: "The HTTP method to use (GET, POST, PUT, DELETE, etc.)",
|
|
4937
|
+
enum: ["GET", "POST", "PUT", "DELETE", "PATCH", "HEAD", "OPTIONS"],
|
|
4938
|
+
default: "GET"
|
|
4939
|
+
},
|
|
4940
|
+
headers: {
|
|
4941
|
+
type: _genai.Type.OBJECT,
|
|
4942
|
+
description: "Request headers to include"
|
|
4943
|
+
},
|
|
4944
|
+
body: {
|
|
4945
|
+
type: _genai.Type.STRING,
|
|
4946
|
+
description: "Request body content (as string, typically JSON)"
|
|
4947
|
+
},
|
|
4948
|
+
params: {
|
|
4949
|
+
type: _genai.Type.OBJECT,
|
|
4950
|
+
description: "URL query parameters to include"
|
|
4951
|
+
},
|
|
4952
|
+
timeout: {
|
|
4953
|
+
type: _genai.Type.INTEGER,
|
|
4954
|
+
description: "Request timeout in milliseconds",
|
|
4955
|
+
default: 1e4
|
|
4976
4956
|
}
|
|
4977
4957
|
},
|
|
4978
|
-
required: ["
|
|
4958
|
+
required: ["url"]
|
|
4979
4959
|
}
|
|
4980
4960
|
};
|
|
4981
4961
|
}
|
|
4982
4962
|
/**
|
|
4983
|
-
* Execute the
|
|
4963
|
+
* Execute the HTTP request
|
|
4984
4964
|
*/
|
|
4985
|
-
async runAsync(args,
|
|
4986
|
-
this.logger.debug(`Executing load_memory with query: ${args.query}`);
|
|
4965
|
+
async runAsync(args, _context) {
|
|
4987
4966
|
try {
|
|
4988
|
-
const
|
|
4967
|
+
const {
|
|
4968
|
+
url,
|
|
4969
|
+
method = "GET",
|
|
4970
|
+
headers = {},
|
|
4971
|
+
body,
|
|
4972
|
+
params,
|
|
4973
|
+
timeout = 1e4
|
|
4974
|
+
} = args;
|
|
4975
|
+
const urlObj = new URL(url);
|
|
4976
|
+
if (params) {
|
|
4977
|
+
Object.entries(params).forEach(([key, value]) => {
|
|
4978
|
+
urlObj.searchParams.append(key, value);
|
|
4979
|
+
});
|
|
4980
|
+
}
|
|
4981
|
+
const requestHeaders = { ...headers };
|
|
4982
|
+
if (body && !requestHeaders["Content-Type"] && this.isValidJson(body)) {
|
|
4983
|
+
requestHeaders["Content-Type"] = "application/json";
|
|
4984
|
+
}
|
|
4985
|
+
const options = {
|
|
4986
|
+
method,
|
|
4987
|
+
headers: requestHeaders,
|
|
4988
|
+
body,
|
|
4989
|
+
signal: AbortSignal.timeout(timeout)
|
|
4990
|
+
};
|
|
4991
|
+
const response = await fetch(urlObj.toString(), options);
|
|
4992
|
+
const responseHeaders = {};
|
|
4993
|
+
response.headers.forEach((value, key) => {
|
|
4994
|
+
responseHeaders[key] = value;
|
|
4995
|
+
});
|
|
4996
|
+
const responseBody = await response.text();
|
|
4989
4997
|
return {
|
|
4990
|
-
|
|
4991
|
-
|
|
4998
|
+
statusCode: response.status,
|
|
4999
|
+
headers: responseHeaders,
|
|
5000
|
+
body: responseBody
|
|
4992
5001
|
};
|
|
4993
5002
|
} catch (error) {
|
|
4994
|
-
console.error("Error searching memory:", error);
|
|
4995
5003
|
return {
|
|
4996
|
-
|
|
4997
|
-
|
|
5004
|
+
statusCode: 0,
|
|
5005
|
+
headers: {},
|
|
5006
|
+
body: "",
|
|
5007
|
+
error: error instanceof Error ? error.message : String(error)
|
|
4998
5008
|
};
|
|
4999
5009
|
}
|
|
5000
5010
|
}
|
|
5001
|
-
|
|
5011
|
+
/**
|
|
5012
|
+
* Check if a string is valid JSON
|
|
5013
|
+
*/
|
|
5014
|
+
isValidJson(str) {
|
|
5015
|
+
try {
|
|
5016
|
+
JSON.parse(str);
|
|
5017
|
+
return true;
|
|
5018
|
+
} catch (e) {
|
|
5019
|
+
return false;
|
|
5020
|
+
}
|
|
5021
|
+
}
|
|
5022
|
+
};
|
|
5002
5023
|
|
|
5003
|
-
// src/tools/common/
|
|
5024
|
+
// src/tools/common/file-operations-tool.ts
|
|
5004
5025
|
init_base_tool();
|
|
5026
|
+
var _promises = require('fs/promises'); var fs2 = _interopRequireWildcard(_promises);
|
|
5027
|
+
var _path = require('path'); var path2 = _interopRequireWildcard(_path);
|
|
5005
5028
|
|
|
5006
|
-
var
|
|
5007
|
-
|
|
5029
|
+
var FileOperationsTool = class extends BaseTool {
|
|
5030
|
+
|
|
5031
|
+
constructor(options) {
|
|
5008
5032
|
super({
|
|
5009
|
-
name: "
|
|
5010
|
-
description: "
|
|
5033
|
+
name: "file_operations",
|
|
5034
|
+
description: "Perform file system operations like reading, writing, and managing files"
|
|
5011
5035
|
});
|
|
5036
|
+
this.basePath = _optionalChain([options, 'optionalAccess', _152 => _152.basePath]) || process.cwd();
|
|
5012
5037
|
}
|
|
5013
5038
|
/**
|
|
5014
5039
|
* Get the function declaration for the tool
|
|
@@ -5020,622 +5045,601 @@ var LoadArtifactsTool = class extends BaseTool {
|
|
|
5020
5045
|
parameters: {
|
|
5021
5046
|
type: _genai.Type.OBJECT,
|
|
5022
5047
|
properties: {
|
|
5023
|
-
|
|
5024
|
-
type: _genai.Type.
|
|
5025
|
-
|
|
5026
|
-
|
|
5027
|
-
|
|
5028
|
-
|
|
5048
|
+
operation: {
|
|
5049
|
+
type: _genai.Type.STRING,
|
|
5050
|
+
description: "The file operation to perform",
|
|
5051
|
+
enum: [
|
|
5052
|
+
"read",
|
|
5053
|
+
"write",
|
|
5054
|
+
"append",
|
|
5055
|
+
"delete",
|
|
5056
|
+
"exists",
|
|
5057
|
+
"list",
|
|
5058
|
+
"mkdir"
|
|
5059
|
+
]
|
|
5060
|
+
},
|
|
5061
|
+
filepath: {
|
|
5062
|
+
type: _genai.Type.STRING,
|
|
5063
|
+
description: "Path to the file or directory (relative to the base path)"
|
|
5064
|
+
},
|
|
5065
|
+
content: {
|
|
5066
|
+
type: _genai.Type.STRING,
|
|
5067
|
+
description: "Content to write to the file (for write and append operations)"
|
|
5068
|
+
},
|
|
5069
|
+
encoding: {
|
|
5070
|
+
type: _genai.Type.STRING,
|
|
5071
|
+
description: "File encoding to use",
|
|
5072
|
+
default: "utf8"
|
|
5029
5073
|
}
|
|
5030
5074
|
},
|
|
5031
|
-
required: []
|
|
5075
|
+
required: ["operation", "filepath"]
|
|
5032
5076
|
}
|
|
5033
5077
|
};
|
|
5034
5078
|
}
|
|
5035
5079
|
/**
|
|
5036
|
-
* Execute the
|
|
5080
|
+
* Execute the file operation
|
|
5037
5081
|
*/
|
|
5038
|
-
async runAsync(args,
|
|
5039
|
-
|
|
5040
|
-
|
|
5082
|
+
async runAsync(args, _context) {
|
|
5083
|
+
try {
|
|
5084
|
+
const resolvedPath = this.resolvePath(args.filepath);
|
|
5085
|
+
this.validatePath(resolvedPath);
|
|
5086
|
+
const encoding = args.encoding || "utf8";
|
|
5087
|
+
switch (args.operation) {
|
|
5088
|
+
case "read":
|
|
5089
|
+
return await this.readFile(resolvedPath, encoding);
|
|
5090
|
+
case "write":
|
|
5091
|
+
return await this.writeFile(
|
|
5092
|
+
resolvedPath,
|
|
5093
|
+
args.content || "",
|
|
5094
|
+
encoding
|
|
5095
|
+
);
|
|
5096
|
+
case "append":
|
|
5097
|
+
return await this.appendFile(
|
|
5098
|
+
resolvedPath,
|
|
5099
|
+
args.content || "",
|
|
5100
|
+
encoding
|
|
5101
|
+
);
|
|
5102
|
+
case "delete":
|
|
5103
|
+
return await this.deleteFile(resolvedPath);
|
|
5104
|
+
case "exists":
|
|
5105
|
+
return await this.fileExists(resolvedPath);
|
|
5106
|
+
case "list":
|
|
5107
|
+
return await this.listDirectory(resolvedPath);
|
|
5108
|
+
case "mkdir":
|
|
5109
|
+
return await this.makeDirectory(resolvedPath);
|
|
5110
|
+
default:
|
|
5111
|
+
throw new Error(`Unsupported operation: ${args.operation}`);
|
|
5112
|
+
}
|
|
5113
|
+
} catch (error) {
|
|
5114
|
+
return {
|
|
5115
|
+
success: false,
|
|
5116
|
+
error: error instanceof Error ? error.message : String(error)
|
|
5117
|
+
};
|
|
5118
|
+
}
|
|
5041
5119
|
}
|
|
5042
5120
|
/**
|
|
5043
|
-
*
|
|
5121
|
+
* Resolve a file path relative to the base path
|
|
5044
5122
|
*/
|
|
5045
|
-
|
|
5046
|
-
|
|
5047
|
-
await this.appendArtifactsToLlmRequest(toolContext, llmRequest);
|
|
5123
|
+
resolvePath(filepath) {
|
|
5124
|
+
return path2.default.isAbsolute(filepath) ? filepath : path2.default.resolve(this.basePath, filepath);
|
|
5048
5125
|
}
|
|
5049
5126
|
/**
|
|
5050
|
-
*
|
|
5127
|
+
* Validate that a path is within the base path for security
|
|
5051
5128
|
*/
|
|
5052
|
-
|
|
5129
|
+
validatePath(filepath) {
|
|
5130
|
+
const normalizedPath = path2.default.normalize(filepath);
|
|
5131
|
+
const normalizedBasePath = path2.default.normalize(this.basePath);
|
|
5132
|
+
if (!normalizedPath.startsWith(normalizedBasePath)) {
|
|
5133
|
+
throw new Error(
|
|
5134
|
+
`Access denied: Can't access paths outside the base directory`
|
|
5135
|
+
);
|
|
5136
|
+
}
|
|
5137
|
+
}
|
|
5138
|
+
/**
|
|
5139
|
+
* Read a file
|
|
5140
|
+
*/
|
|
5141
|
+
async readFile(filepath, encoding) {
|
|
5053
5142
|
try {
|
|
5054
|
-
const
|
|
5055
|
-
|
|
5056
|
-
|
|
5057
|
-
|
|
5058
|
-
|
|
5059
|
-
`You have a list of artifacts:
|
|
5060
|
-
${JSON.stringify(artifactNames)}
|
|
5061
|
-
|
|
5062
|
-
When the user asks questions about any of the artifacts, you should call the
|
|
5063
|
-
\`load_artifacts\` function to load the artifact. Do not generate any text other
|
|
5064
|
-
than the function call.
|
|
5065
|
-
`
|
|
5066
|
-
];
|
|
5067
|
-
if (llmRequest.appendInstructions) {
|
|
5068
|
-
llmRequest.appendInstructions(instructions);
|
|
5069
|
-
}
|
|
5070
|
-
if (llmRequest.contents && llmRequest.contents.length > 0) {
|
|
5071
|
-
const lastContent = llmRequest.contents[llmRequest.contents.length - 1];
|
|
5072
|
-
if (lastContent.parts && lastContent.parts.length > 0) {
|
|
5073
|
-
const firstPart = lastContent.parts[0];
|
|
5074
|
-
const functionResponse = this.extractFunctionResponse(firstPart);
|
|
5075
|
-
if (functionResponse && functionResponse.name === "load_artifacts") {
|
|
5076
|
-
const requestedArtifactNames = functionResponse.response.artifact_names || [];
|
|
5077
|
-
for (const artifactName of requestedArtifactNames) {
|
|
5078
|
-
try {
|
|
5079
|
-
const artifact = await toolContext.loadArtifact(artifactName);
|
|
5080
|
-
if (artifact) {
|
|
5081
|
-
llmRequest.contents.push({
|
|
5082
|
-
role: "user",
|
|
5083
|
-
parts: [
|
|
5084
|
-
{
|
|
5085
|
-
text: `Artifact ${artifactName} is:`
|
|
5086
|
-
},
|
|
5087
|
-
artifact
|
|
5088
|
-
]
|
|
5089
|
-
});
|
|
5090
|
-
}
|
|
5091
|
-
} catch (error) {
|
|
5092
|
-
console.error(
|
|
5093
|
-
`Failed to load artifact ${artifactName}:`,
|
|
5094
|
-
error
|
|
5095
|
-
);
|
|
5096
|
-
}
|
|
5097
|
-
}
|
|
5098
|
-
}
|
|
5099
|
-
}
|
|
5100
|
-
}
|
|
5143
|
+
const content = await fs2.default.readFile(filepath, { encoding });
|
|
5144
|
+
return {
|
|
5145
|
+
success: true,
|
|
5146
|
+
data: content
|
|
5147
|
+
};
|
|
5101
5148
|
} catch (error) {
|
|
5102
|
-
|
|
5149
|
+
return {
|
|
5150
|
+
success: false,
|
|
5151
|
+
error: `Failed to read file: ${error instanceof Error ? error.message : String(error)}`
|
|
5152
|
+
};
|
|
5103
5153
|
}
|
|
5104
5154
|
}
|
|
5105
5155
|
/**
|
|
5106
|
-
*
|
|
5156
|
+
* Write to a file
|
|
5107
5157
|
*/
|
|
5108
|
-
|
|
5109
|
-
|
|
5110
|
-
|
|
5158
|
+
async writeFile(filepath, content, encoding) {
|
|
5159
|
+
try {
|
|
5160
|
+
const dir = path2.default.dirname(filepath);
|
|
5161
|
+
await fs2.default.mkdir(dir, { recursive: true });
|
|
5162
|
+
await fs2.default.writeFile(filepath, content, { encoding });
|
|
5163
|
+
return {
|
|
5164
|
+
success: true
|
|
5165
|
+
};
|
|
5166
|
+
} catch (error) {
|
|
5167
|
+
return {
|
|
5168
|
+
success: false,
|
|
5169
|
+
error: `Failed to write to file: ${error instanceof Error ? error.message : String(error)}`
|
|
5170
|
+
};
|
|
5111
5171
|
}
|
|
5112
|
-
return null;
|
|
5113
5172
|
}
|
|
5114
|
-
|
|
5115
|
-
|
|
5116
|
-
|
|
5117
|
-
|
|
5118
|
-
|
|
5119
|
-
|
|
5120
|
-
|
|
5121
|
-
|
|
5122
|
-
|
|
5123
|
-
|
|
5124
|
-
|
|
5125
|
-
|
|
5126
|
-
|
|
5127
|
-
|
|
5128
|
-
|
|
5129
|
-
|
|
5130
|
-
|
|
5131
|
-
|
|
5132
|
-
|
|
5133
|
-
|
|
5134
|
-
|
|
5135
|
-
|
|
5136
|
-
|
|
5137
|
-
|
|
5138
|
-
|
|
5139
|
-
|
|
5140
|
-
}
|
|
5141
|
-
|
|
5142
|
-
|
|
5143
|
-
|
|
5144
|
-
|
|
5145
|
-
|
|
5146
|
-
|
|
5147
|
-
this.type = type;
|
|
5148
|
-
this.originalError = originalError;
|
|
5173
|
+
/**
|
|
5174
|
+
* Append to a file
|
|
5175
|
+
*/
|
|
5176
|
+
async appendFile(filepath, content, encoding) {
|
|
5177
|
+
try {
|
|
5178
|
+
const dir = path2.default.dirname(filepath);
|
|
5179
|
+
await fs2.default.mkdir(dir, { recursive: true });
|
|
5180
|
+
await fs2.default.appendFile(filepath, content, { encoding });
|
|
5181
|
+
return {
|
|
5182
|
+
success: true
|
|
5183
|
+
};
|
|
5184
|
+
} catch (error) {
|
|
5185
|
+
return {
|
|
5186
|
+
success: false,
|
|
5187
|
+
error: `Failed to append to file: ${error instanceof Error ? error.message : String(error)}`
|
|
5188
|
+
};
|
|
5189
|
+
}
|
|
5190
|
+
}
|
|
5191
|
+
/**
|
|
5192
|
+
* Delete a file
|
|
5193
|
+
*/
|
|
5194
|
+
async deleteFile(filepath) {
|
|
5195
|
+
try {
|
|
5196
|
+
await fs2.default.unlink(filepath);
|
|
5197
|
+
return {
|
|
5198
|
+
success: true
|
|
5199
|
+
};
|
|
5200
|
+
} catch (error) {
|
|
5201
|
+
return {
|
|
5202
|
+
success: false,
|
|
5203
|
+
error: `Failed to delete file: ${error instanceof Error ? error.message : String(error)}`
|
|
5204
|
+
};
|
|
5205
|
+
}
|
|
5149
5206
|
}
|
|
5150
|
-
|
|
5151
|
-
|
|
5152
|
-
|
|
5153
|
-
|
|
5154
|
-
|
|
5155
|
-
|
|
5156
|
-
|
|
5157
|
-
|
|
5207
|
+
/**
|
|
5208
|
+
* Check if a file exists
|
|
5209
|
+
*/
|
|
5210
|
+
async fileExists(filepath) {
|
|
5211
|
+
try {
|
|
5212
|
+
await fs2.default.access(filepath);
|
|
5213
|
+
return {
|
|
5214
|
+
success: true,
|
|
5215
|
+
data: true
|
|
5216
|
+
};
|
|
5217
|
+
} catch (e3) {
|
|
5218
|
+
return {
|
|
5219
|
+
success: true,
|
|
5220
|
+
data: false
|
|
5221
|
+
};
|
|
5222
|
+
}
|
|
5158
5223
|
}
|
|
5159
5224
|
/**
|
|
5160
|
-
*
|
|
5225
|
+
* List directory contents
|
|
5161
5226
|
*/
|
|
5162
|
-
async
|
|
5227
|
+
async listDirectory(dirpath) {
|
|
5163
5228
|
try {
|
|
5164
|
-
|
|
5165
|
-
|
|
5166
|
-
|
|
5167
|
-
|
|
5168
|
-
|
|
5169
|
-
|
|
5170
|
-
|
|
5171
|
-
|
|
5172
|
-
|
|
5173
|
-
|
|
5174
|
-
|
|
5175
|
-
|
|
5176
|
-
|
|
5177
|
-
|
|
5178
|
-
)
|
|
5179
|
-
throw new McpError(
|
|
5180
|
-
`Invalid sampling request: ${validationResult.error.message}`,
|
|
5181
|
-
"INVALID_REQUEST_ERROR" /* INVALID_REQUEST_ERROR */
|
|
5182
|
-
);
|
|
5183
|
-
}
|
|
5184
|
-
const mcpParams = request.params;
|
|
5185
|
-
if (!mcpParams.messages || !Array.isArray(mcpParams.messages)) {
|
|
5186
|
-
throw new McpError(
|
|
5187
|
-
"Invalid sampling request: messages array is required",
|
|
5188
|
-
"INVALID_REQUEST_ERROR" /* INVALID_REQUEST_ERROR */
|
|
5189
|
-
);
|
|
5190
|
-
}
|
|
5191
|
-
if (!mcpParams.maxTokens || mcpParams.maxTokens <= 0) {
|
|
5192
|
-
throw new McpError(
|
|
5193
|
-
"Invalid sampling request: maxTokens must be a positive number",
|
|
5194
|
-
"INVALID_REQUEST_ERROR" /* INVALID_REQUEST_ERROR */
|
|
5195
|
-
);
|
|
5196
|
-
}
|
|
5197
|
-
this.logger.debug("Converting MCP request to ADK format");
|
|
5198
|
-
const adkContents = this.convertMcpMessagesToADK(
|
|
5199
|
-
mcpParams.messages,
|
|
5200
|
-
mcpParams.systemPrompt
|
|
5201
|
-
);
|
|
5202
|
-
const requestModel = mcpParams.model || "gemini-2.0-flash";
|
|
5203
|
-
const adkRequest = new LlmRequest({
|
|
5204
|
-
model: requestModel,
|
|
5205
|
-
contents: adkContents,
|
|
5206
|
-
config: {
|
|
5207
|
-
temperature: mcpParams.temperature,
|
|
5208
|
-
maxOutputTokens: mcpParams.maxTokens
|
|
5209
|
-
}
|
|
5210
|
-
});
|
|
5211
|
-
this.logger.debug("Calling ADK sampling handler");
|
|
5212
|
-
const adkResponse = await this.samplingHandler(adkRequest);
|
|
5213
|
-
this.logger.debug("Converting ADK response to MCP format");
|
|
5214
|
-
const mcpResponse = this.convertADKResponseToMcp(
|
|
5215
|
-
adkResponse,
|
|
5216
|
-
requestModel
|
|
5229
|
+
const entries = await fs2.default.readdir(dirpath, { withFileTypes: true });
|
|
5230
|
+
const results = await Promise.all(
|
|
5231
|
+
entries.map(async (entry) => {
|
|
5232
|
+
const entryPath = path2.default.join(dirpath, entry.name);
|
|
5233
|
+
const stats = await fs2.default.stat(entryPath);
|
|
5234
|
+
return {
|
|
5235
|
+
name: entry.name,
|
|
5236
|
+
path: entryPath,
|
|
5237
|
+
isFile: entry.isFile(),
|
|
5238
|
+
isDirectory: entry.isDirectory(),
|
|
5239
|
+
size: stats.size,
|
|
5240
|
+
created: stats.birthtime,
|
|
5241
|
+
modified: stats.mtime
|
|
5242
|
+
};
|
|
5243
|
+
})
|
|
5217
5244
|
);
|
|
5218
|
-
|
|
5219
|
-
|
|
5220
|
-
|
|
5221
|
-
|
|
5222
|
-
responseValidation.error
|
|
5223
|
-
);
|
|
5224
|
-
throw new McpError(
|
|
5225
|
-
`Invalid response generated: ${responseValidation.error.message}`,
|
|
5226
|
-
"SAMPLING_ERROR" /* SAMPLING_ERROR */
|
|
5227
|
-
);
|
|
5228
|
-
}
|
|
5229
|
-
return mcpResponse;
|
|
5245
|
+
return {
|
|
5246
|
+
success: true,
|
|
5247
|
+
data: results
|
|
5248
|
+
};
|
|
5230
5249
|
} catch (error) {
|
|
5231
|
-
|
|
5232
|
-
|
|
5233
|
-
|
|
5234
|
-
}
|
|
5235
|
-
throw new McpError(
|
|
5236
|
-
`Sampling request failed: ${error instanceof Error ? error.message : String(error)}`,
|
|
5237
|
-
"SAMPLING_ERROR" /* SAMPLING_ERROR */,
|
|
5238
|
-
error instanceof Error ? error : void 0
|
|
5239
|
-
);
|
|
5250
|
+
return {
|
|
5251
|
+
success: false,
|
|
5252
|
+
error: `Failed to list directory: ${error instanceof Error ? error.message : String(error)}`
|
|
5253
|
+
};
|
|
5240
5254
|
}
|
|
5241
5255
|
}
|
|
5242
5256
|
/**
|
|
5243
|
-
*
|
|
5257
|
+
* Create a directory
|
|
5244
5258
|
*/
|
|
5245
|
-
|
|
5246
|
-
|
|
5247
|
-
|
|
5248
|
-
|
|
5249
|
-
|
|
5250
|
-
|
|
5251
|
-
|
|
5252
|
-
|
|
5259
|
+
async makeDirectory(dirpath) {
|
|
5260
|
+
try {
|
|
5261
|
+
await fs2.default.mkdir(dirpath, { recursive: true });
|
|
5262
|
+
return {
|
|
5263
|
+
success: true
|
|
5264
|
+
};
|
|
5265
|
+
} catch (error) {
|
|
5266
|
+
return {
|
|
5267
|
+
success: false,
|
|
5268
|
+
error: `Failed to create directory: ${error instanceof Error ? error.message : String(error)}`
|
|
5269
|
+
};
|
|
5253
5270
|
}
|
|
5254
|
-
|
|
5255
|
-
|
|
5256
|
-
|
|
5257
|
-
|
|
5258
|
-
|
|
5271
|
+
}
|
|
5272
|
+
};
|
|
5273
|
+
|
|
5274
|
+
// src/tools/common/user-interaction-tool.ts
|
|
5275
|
+
init_base_tool();
|
|
5276
|
+
|
|
5277
|
+
var UserInteractionTool = class extends BaseTool {
|
|
5278
|
+
constructor() {
|
|
5279
|
+
super({
|
|
5280
|
+
name: "user_interaction",
|
|
5281
|
+
description: "Prompt the user for input during agent execution",
|
|
5282
|
+
isLongRunning: true
|
|
5283
|
+
});
|
|
5259
5284
|
}
|
|
5260
5285
|
/**
|
|
5261
|
-
*
|
|
5286
|
+
* Get the function declaration for the tool
|
|
5262
5287
|
*/
|
|
5263
|
-
|
|
5264
|
-
|
|
5265
|
-
|
|
5266
|
-
|
|
5267
|
-
|
|
5268
|
-
|
|
5288
|
+
getDeclaration() {
|
|
5289
|
+
return {
|
|
5290
|
+
name: this.name,
|
|
5291
|
+
description: this.description,
|
|
5292
|
+
parameters: {
|
|
5293
|
+
type: _genai.Type.OBJECT,
|
|
5294
|
+
properties: {
|
|
5295
|
+
prompt: {
|
|
5296
|
+
type: _genai.Type.STRING,
|
|
5297
|
+
description: "The prompt message to display to the user"
|
|
5298
|
+
},
|
|
5299
|
+
options: {
|
|
5300
|
+
type: _genai.Type.ARRAY,
|
|
5301
|
+
description: "Optional array of choices to present to the user",
|
|
5302
|
+
items: {
|
|
5303
|
+
type: _genai.Type.STRING
|
|
5304
|
+
}
|
|
5305
|
+
},
|
|
5306
|
+
defaultValue: {
|
|
5307
|
+
type: _genai.Type.STRING,
|
|
5308
|
+
description: "Optional default value for the input field"
|
|
5309
|
+
}
|
|
5310
|
+
},
|
|
5311
|
+
required: ["prompt"]
|
|
5312
|
+
}
|
|
5269
5313
|
};
|
|
5270
|
-
this.logger.debug(
|
|
5271
|
-
`Converted MCP message - role: ${mcpMessage.role} -> ${adkRole}, content type: ${mcpMessage.content.type}`
|
|
5272
|
-
);
|
|
5273
|
-
return adkContent;
|
|
5274
5314
|
}
|
|
5275
5315
|
/**
|
|
5276
|
-
*
|
|
5316
|
+
* Execute the user interaction
|
|
5277
5317
|
*/
|
|
5278
|
-
|
|
5279
|
-
|
|
5280
|
-
const
|
|
5281
|
-
|
|
5282
|
-
|
|
5283
|
-
|
|
5284
|
-
|
|
5285
|
-
|
|
5286
|
-
parts.push({ text: mcpContent.text });
|
|
5318
|
+
async runAsync(args, context4) {
|
|
5319
|
+
try {
|
|
5320
|
+
const actions = context4.actions;
|
|
5321
|
+
if (!actions || !actions.promptUser) {
|
|
5322
|
+
return {
|
|
5323
|
+
success: false,
|
|
5324
|
+
error: "User interaction is not supported in the current environment"
|
|
5325
|
+
};
|
|
5287
5326
|
}
|
|
5288
|
-
if (
|
|
5289
|
-
|
|
5290
|
-
parts.push({
|
|
5291
|
-
inlineData: {
|
|
5292
|
-
data: mcpContent.data,
|
|
5293
|
-
mimeType
|
|
5294
|
-
}
|
|
5295
|
-
});
|
|
5327
|
+
if (actions.skipSummarization) {
|
|
5328
|
+
actions.skipSummarization(true);
|
|
5296
5329
|
}
|
|
5297
|
-
|
|
5298
|
-
|
|
5299
|
-
|
|
5300
|
-
|
|
5301
|
-
|
|
5330
|
+
const promptOptions = args.options && args.options.length > 0 ? {
|
|
5331
|
+
choices: args.options
|
|
5332
|
+
} : void 0;
|
|
5333
|
+
const response = await actions.promptUser({
|
|
5334
|
+
prompt: args.prompt,
|
|
5335
|
+
defaultValue: args.defaultValue,
|
|
5336
|
+
options: promptOptions
|
|
5337
|
+
});
|
|
5338
|
+
return {
|
|
5339
|
+
success: true,
|
|
5340
|
+
userInput: response
|
|
5341
|
+
};
|
|
5342
|
+
} catch (error) {
|
|
5343
|
+
return {
|
|
5344
|
+
success: false,
|
|
5345
|
+
error: error instanceof Error ? error.message : String(error)
|
|
5346
|
+
};
|
|
5347
|
+
}
|
|
5302
5348
|
}
|
|
5349
|
+
};
|
|
5350
|
+
|
|
5351
|
+
// src/tools/common/exit-loop-tool.ts
|
|
5352
|
+
init_logger();
|
|
5353
|
+
init_base_tool();
|
|
5354
|
+
var ExitLoopTool = (_class19 = class extends BaseTool {
|
|
5355
|
+
__init33() {this.logger = new Logger({ name: "ExitLoopTool" })}
|
|
5303
5356
|
/**
|
|
5304
|
-
*
|
|
5357
|
+
* Constructor for ExitLoopTool
|
|
5305
5358
|
*/
|
|
5306
|
-
|
|
5307
|
-
|
|
5308
|
-
|
|
5309
|
-
|
|
5310
|
-
}
|
|
5311
|
-
if (adkResponse.content) {
|
|
5312
|
-
if (typeof adkResponse.content === "string") {
|
|
5313
|
-
responseText = adkResponse.content;
|
|
5314
|
-
} else if (adkResponse.content.parts) {
|
|
5315
|
-
responseText = adkResponse.content.parts.map((part) => {
|
|
5316
|
-
return typeof part.text === "string" ? part.text : "";
|
|
5317
|
-
}).join("");
|
|
5318
|
-
}
|
|
5319
|
-
}
|
|
5320
|
-
}
|
|
5321
|
-
const mcpResponse = {
|
|
5322
|
-
model,
|
|
5323
|
-
// Use the model from the request
|
|
5324
|
-
role: "assistant",
|
|
5325
|
-
// ADK responses are always from assistant
|
|
5326
|
-
content: {
|
|
5327
|
-
type: "text",
|
|
5328
|
-
text: responseText
|
|
5329
|
-
}
|
|
5330
|
-
};
|
|
5331
|
-
this.logger.debug(`Received content: ${responseText}`);
|
|
5332
|
-
return mcpResponse;
|
|
5359
|
+
constructor() {
|
|
5360
|
+
super({
|
|
5361
|
+
name: "exit_loop",
|
|
5362
|
+
description: "Exits the loop. Call this function only when you are instructed to do so."
|
|
5363
|
+
});_class19.prototype.__init33.call(this);;
|
|
5333
5364
|
}
|
|
5334
5365
|
/**
|
|
5335
|
-
*
|
|
5366
|
+
* Execute the exit loop action
|
|
5336
5367
|
*/
|
|
5337
|
-
|
|
5338
|
-
this.
|
|
5339
|
-
|
|
5368
|
+
async runAsync(_args, context4) {
|
|
5369
|
+
this.logger.debug("Executing exit loop tool");
|
|
5370
|
+
context4.actions.escalate = true;
|
|
5340
5371
|
}
|
|
5341
|
-
},
|
|
5342
|
-
function createSamplingHandler(handler) {
|
|
5343
|
-
return handler;
|
|
5344
|
-
}
|
|
5372
|
+
}, _class19);
|
|
5345
5373
|
|
|
5346
|
-
// src/tools/
|
|
5347
|
-
|
|
5348
|
-
|
|
5349
|
-
let attempt = 0;
|
|
5350
|
-
while (attempt <= maxRetries) {
|
|
5351
|
-
try {
|
|
5352
|
-
return await fn.apply(instance, args);
|
|
5353
|
-
} catch (error) {
|
|
5354
|
-
const isClosedResourceError = error instanceof Error && (error.message.includes("closed") || error.message.includes("ECONNRESET") || error.message.includes("socket hang up"));
|
|
5355
|
-
if (!isClosedResourceError || attempt >= maxRetries) {
|
|
5356
|
-
throw error;
|
|
5357
|
-
}
|
|
5358
|
-
console.warn(
|
|
5359
|
-
`Resource closed, reinitializing (attempt ${attempt + 1}/${maxRetries + 1})...`
|
|
5360
|
-
);
|
|
5361
|
-
try {
|
|
5362
|
-
await reinitMethod(instance);
|
|
5363
|
-
} catch (reinitError) {
|
|
5364
|
-
console.error("Error reinitializing resources:", reinitError);
|
|
5365
|
-
throw new Error(`Failed to reinitialize resources: ${reinitError}`);
|
|
5366
|
-
}
|
|
5367
|
-
attempt++;
|
|
5368
|
-
}
|
|
5369
|
-
}
|
|
5370
|
-
throw new Error("Unexpected end of retry loop");
|
|
5371
|
-
};
|
|
5372
|
-
}
|
|
5374
|
+
// src/tools/common/get-user-choice-tool.ts
|
|
5375
|
+
init_logger();
|
|
5376
|
+
init_base_tool();
|
|
5373
5377
|
|
|
5374
|
-
|
|
5375
|
-
|
|
5376
|
-
|
|
5377
|
-
|
|
5378
|
-
|
|
5379
|
-
|
|
5380
|
-
|
|
5381
|
-
|
|
5382
|
-
|
|
5383
|
-
|
|
5384
|
-
|
|
5385
|
-
this.mcpSamplingHandler = new McpSamplingHandler(config.samplingHandler);
|
|
5386
|
-
}
|
|
5378
|
+
var GetUserChoiceTool = (_class20 = class extends BaseTool {
|
|
5379
|
+
__init34() {this.logger = new Logger({ name: "GetUserChoiceTool" })}
|
|
5380
|
+
/**
|
|
5381
|
+
* Constructor for GetUserChoiceTool
|
|
5382
|
+
*/
|
|
5383
|
+
constructor() {
|
|
5384
|
+
super({
|
|
5385
|
+
name: "get_user_choice",
|
|
5386
|
+
description: "This tool provides the options to the user and asks them to choose one. Use this tool when you need the user to make a selection between multiple options. Do not list options in your response - use this tool instead.",
|
|
5387
|
+
isLongRunning: true
|
|
5388
|
+
});_class20.prototype.__init34.call(this);;
|
|
5387
5389
|
}
|
|
5388
5390
|
/**
|
|
5389
|
-
*
|
|
5390
|
-
* Will create a new client if one doesn't exist yet.
|
|
5391
|
+
* Get the function declaration for the tool
|
|
5391
5392
|
*/
|
|
5392
|
-
|
|
5393
|
-
|
|
5394
|
-
|
|
5395
|
-
|
|
5396
|
-
|
|
5397
|
-
|
|
5398
|
-
|
|
5399
|
-
|
|
5400
|
-
|
|
5401
|
-
|
|
5402
|
-
|
|
5403
|
-
|
|
5404
|
-
|
|
5405
|
-
|
|
5406
|
-
|
|
5407
|
-
|
|
5408
|
-
|
|
5409
|
-
version: "0.0.1"
|
|
5410
|
-
},
|
|
5411
|
-
{
|
|
5412
|
-
capabilities: {
|
|
5413
|
-
prompts: {},
|
|
5414
|
-
resources: {},
|
|
5415
|
-
tools: {},
|
|
5416
|
-
sampling: {}
|
|
5417
|
-
// Enable sampling capability
|
|
5393
|
+
getDeclaration() {
|
|
5394
|
+
return {
|
|
5395
|
+
name: this.name,
|
|
5396
|
+
description: this.description,
|
|
5397
|
+
parameters: {
|
|
5398
|
+
type: _genai.Type.OBJECT,
|
|
5399
|
+
properties: {
|
|
5400
|
+
options: {
|
|
5401
|
+
type: _genai.Type.ARRAY,
|
|
5402
|
+
description: "List of options for the user to choose from",
|
|
5403
|
+
items: {
|
|
5404
|
+
type: _genai.Type.STRING
|
|
5405
|
+
}
|
|
5406
|
+
},
|
|
5407
|
+
question: {
|
|
5408
|
+
type: _genai.Type.STRING,
|
|
5409
|
+
description: "The question or prompt to show the user before presenting options"
|
|
5418
5410
|
}
|
|
5419
|
-
}
|
|
5420
|
-
|
|
5421
|
-
const connectPromise = client.connect(this.transport);
|
|
5422
|
-
if (this.config.timeout) {
|
|
5423
|
-
const timeoutPromise = new Promise((_, reject) => {
|
|
5424
|
-
setTimeout(() => {
|
|
5425
|
-
reject(
|
|
5426
|
-
new McpError(
|
|
5427
|
-
`MCP client connection timed out after ${this.config.timeout}ms`,
|
|
5428
|
-
"timeout_error" /* TIMEOUT_ERROR */
|
|
5429
|
-
)
|
|
5430
|
-
);
|
|
5431
|
-
}, this.config.timeout);
|
|
5432
|
-
});
|
|
5433
|
-
await Promise.race([connectPromise, timeoutPromise]);
|
|
5434
|
-
} else {
|
|
5435
|
-
await connectPromise;
|
|
5436
|
-
}
|
|
5437
|
-
await this.setupSamplingHandler(client);
|
|
5438
|
-
this.logger.debug("\u2705 MCP client connected successfully");
|
|
5439
|
-
this.client = client;
|
|
5440
|
-
return client;
|
|
5441
|
-
} catch (error) {
|
|
5442
|
-
await this.cleanupResources();
|
|
5443
|
-
if (!(error instanceof McpError)) {
|
|
5444
|
-
this.logger.error("Failed to initialize MCP client:", error);
|
|
5445
|
-
throw new McpError(
|
|
5446
|
-
`Failed to initialize MCP client: ${error instanceof Error ? error.message : String(error)}`,
|
|
5447
|
-
"connection_error" /* CONNECTION_ERROR */,
|
|
5448
|
-
error instanceof Error ? error : void 0
|
|
5449
|
-
);
|
|
5411
|
+
},
|
|
5412
|
+
required: ["options"]
|
|
5450
5413
|
}
|
|
5451
|
-
|
|
5414
|
+
};
|
|
5415
|
+
}
|
|
5416
|
+
/**
|
|
5417
|
+
* Execute the user choice action
|
|
5418
|
+
* This is a long running operation that will return null initially
|
|
5419
|
+
* and the actual choice will be provided asynchronously
|
|
5420
|
+
*/
|
|
5421
|
+
async runAsync(args, context4) {
|
|
5422
|
+
this.logger.debug(
|
|
5423
|
+
`Executing get_user_choice with options: ${args.options.join(", ")}`
|
|
5424
|
+
);
|
|
5425
|
+
if (args.question) {
|
|
5426
|
+
this.logger.debug(`Question: ${args.question}`);
|
|
5452
5427
|
}
|
|
5428
|
+
context4.actions.skipSummarization = true;
|
|
5429
|
+
return null;
|
|
5430
|
+
}
|
|
5431
|
+
}, _class20);
|
|
5432
|
+
|
|
5433
|
+
// src/tools/common/transfer-to-agent-tool.ts
|
|
5434
|
+
init_logger();
|
|
5435
|
+
init_base_tool();
|
|
5436
|
+
|
|
5437
|
+
var TransferToAgentTool = (_class21 = class extends BaseTool {
|
|
5438
|
+
__init35() {this.logger = new Logger({ name: "TransferToAgentTool" })}
|
|
5439
|
+
/**
|
|
5440
|
+
* Constructor for TransferToAgentTool
|
|
5441
|
+
*/
|
|
5442
|
+
constructor() {
|
|
5443
|
+
super({
|
|
5444
|
+
name: "transfer_to_agent",
|
|
5445
|
+
description: "Transfer the question to another agent when it's more suitable to answer the user's question according to the agent's description. Use this function when you determine that another agent in the system would be better equipped to handle the user's request based on their specialized capabilities and expertise areas."
|
|
5446
|
+
});_class21.prototype.__init35.call(this);;
|
|
5453
5447
|
}
|
|
5454
5448
|
/**
|
|
5455
|
-
*
|
|
5449
|
+
* Get the function declaration for the tool
|
|
5456
5450
|
*/
|
|
5457
|
-
|
|
5458
|
-
|
|
5459
|
-
|
|
5460
|
-
|
|
5461
|
-
|
|
5462
|
-
|
|
5463
|
-
|
|
5464
|
-
|
|
5465
|
-
|
|
5466
|
-
|
|
5467
|
-
};
|
|
5468
|
-
return new (0, _ssejs.SSEClientTransport)(
|
|
5469
|
-
new URL(this.config.transport.serverUrl),
|
|
5470
|
-
{
|
|
5471
|
-
requestInit: {
|
|
5472
|
-
headers,
|
|
5473
|
-
...this.config.timeout ? { timeout: this.config.timeout } : {}
|
|
5474
|
-
}
|
|
5451
|
+
getDeclaration() {
|
|
5452
|
+
return {
|
|
5453
|
+
name: this.name,
|
|
5454
|
+
description: this.description,
|
|
5455
|
+
parameters: {
|
|
5456
|
+
type: _genai.Type.OBJECT,
|
|
5457
|
+
properties: {
|
|
5458
|
+
agent_name: {
|
|
5459
|
+
type: _genai.Type.STRING,
|
|
5460
|
+
description: "The name of the agent to transfer control to"
|
|
5475
5461
|
}
|
|
5476
|
-
|
|
5462
|
+
},
|
|
5463
|
+
required: ["agent_name"]
|
|
5477
5464
|
}
|
|
5478
|
-
|
|
5479
|
-
|
|
5480
|
-
|
|
5481
|
-
|
|
5482
|
-
|
|
5483
|
-
|
|
5484
|
-
|
|
5485
|
-
|
|
5486
|
-
});
|
|
5487
|
-
} catch (error) {
|
|
5488
|
-
throw new McpError(
|
|
5489
|
-
`Failed to create transport: ${error instanceof Error ? error.message : String(error)}`,
|
|
5490
|
-
"connection_error" /* CONNECTION_ERROR */,
|
|
5491
|
-
error instanceof Error ? error : void 0
|
|
5492
|
-
);
|
|
5493
|
-
}
|
|
5465
|
+
};
|
|
5466
|
+
}
|
|
5467
|
+
/**
|
|
5468
|
+
* Execute the transfer to agent action
|
|
5469
|
+
*/
|
|
5470
|
+
async runAsync(args, context4) {
|
|
5471
|
+
this.logger.debug(`Executing transfer to agent: ${args.agent_name}`);
|
|
5472
|
+
context4.actions.transferToAgent = args.agent_name;
|
|
5494
5473
|
}
|
|
5474
|
+
}, _class21);
|
|
5475
|
+
|
|
5476
|
+
// src/tools/common/load-memory-tool.ts
|
|
5477
|
+
init_logger();
|
|
5478
|
+
init_base_tool();
|
|
5479
|
+
|
|
5480
|
+
var LoadMemoryTool = (_class22 = class extends BaseTool {
|
|
5481
|
+
__init36() {this.logger = new Logger({ name: "LoadMemoryTool" })}
|
|
5495
5482
|
/**
|
|
5496
|
-
*
|
|
5497
|
-
* Used by the retry mechanism.
|
|
5483
|
+
* Constructor for LoadMemoryTool
|
|
5498
5484
|
*/
|
|
5499
|
-
|
|
5500
|
-
|
|
5501
|
-
|
|
5502
|
-
|
|
5503
|
-
this
|
|
5504
|
-
await this.initialize();
|
|
5485
|
+
constructor() {
|
|
5486
|
+
super({
|
|
5487
|
+
name: "load_memory",
|
|
5488
|
+
description: "Loads the memory for the current user based on a query."
|
|
5489
|
+
});_class22.prototype.__init36.call(this);;
|
|
5505
5490
|
}
|
|
5506
5491
|
/**
|
|
5507
|
-
*
|
|
5508
|
-
* Similar to Python's AsyncExitStack.aclose() functionality.
|
|
5492
|
+
* Get the function declaration for the tool
|
|
5509
5493
|
*/
|
|
5510
|
-
|
|
5511
|
-
|
|
5512
|
-
this.
|
|
5513
|
-
|
|
5514
|
-
|
|
5515
|
-
|
|
5516
|
-
|
|
5494
|
+
getDeclaration() {
|
|
5495
|
+
return {
|
|
5496
|
+
name: this.name,
|
|
5497
|
+
description: this.description,
|
|
5498
|
+
parameters: {
|
|
5499
|
+
type: _genai.Type.OBJECT,
|
|
5500
|
+
properties: {
|
|
5501
|
+
query: {
|
|
5502
|
+
type: _genai.Type.STRING,
|
|
5503
|
+
description: "The query to load memories for"
|
|
5517
5504
|
}
|
|
5518
|
-
}
|
|
5519
|
-
|
|
5520
|
-
}
|
|
5521
|
-
if (this.transport && typeof this.transport.close === "function") {
|
|
5522
|
-
await this.transport.close();
|
|
5505
|
+
},
|
|
5506
|
+
required: ["query"]
|
|
5523
5507
|
}
|
|
5524
|
-
|
|
5508
|
+
};
|
|
5509
|
+
}
|
|
5510
|
+
/**
|
|
5511
|
+
* Execute the memory loading action
|
|
5512
|
+
*/
|
|
5513
|
+
async runAsync(args, context4) {
|
|
5514
|
+
this.logger.debug(`Executing load_memory with query: ${args.query}`);
|
|
5515
|
+
try {
|
|
5516
|
+
const searchResult = await context4.searchMemory(args.query);
|
|
5517
|
+
return {
|
|
5518
|
+
memories: searchResult.memories || [],
|
|
5519
|
+
count: _optionalChain([searchResult, 'access', _153 => _153.memories, 'optionalAccess', _154 => _154.length]) || 0
|
|
5520
|
+
};
|
|
5525
5521
|
} catch (error) {
|
|
5526
|
-
|
|
5527
|
-
|
|
5528
|
-
|
|
5529
|
-
|
|
5530
|
-
|
|
5522
|
+
console.error("Error searching memory:", error);
|
|
5523
|
+
return {
|
|
5524
|
+
error: "Memory search failed",
|
|
5525
|
+
message: error instanceof Error ? error.message : String(error)
|
|
5526
|
+
};
|
|
5531
5527
|
}
|
|
5532
5528
|
}
|
|
5529
|
+
}, _class22);
|
|
5530
|
+
|
|
5531
|
+
// src/tools/common/load-artifacts-tool.ts
|
|
5532
|
+
init_base_tool();
|
|
5533
|
+
|
|
5534
|
+
var LoadArtifactsTool = class extends BaseTool {
|
|
5535
|
+
constructor() {
|
|
5536
|
+
super({
|
|
5537
|
+
name: "load_artifacts",
|
|
5538
|
+
description: "Loads the artifacts and adds them to the session."
|
|
5539
|
+
});
|
|
5540
|
+
}
|
|
5533
5541
|
/**
|
|
5534
|
-
*
|
|
5542
|
+
* Get the function declaration for the tool
|
|
5535
5543
|
*/
|
|
5536
|
-
|
|
5537
|
-
|
|
5538
|
-
|
|
5539
|
-
|
|
5540
|
-
|
|
5541
|
-
|
|
5542
|
-
|
|
5543
|
-
|
|
5544
|
-
|
|
5544
|
+
getDeclaration() {
|
|
5545
|
+
return {
|
|
5546
|
+
name: this.name,
|
|
5547
|
+
description: this.description,
|
|
5548
|
+
parameters: {
|
|
5549
|
+
type: _genai.Type.OBJECT,
|
|
5550
|
+
properties: {
|
|
5551
|
+
artifact_names: {
|
|
5552
|
+
type: _genai.Type.ARRAY,
|
|
5553
|
+
items: {
|
|
5554
|
+
type: _genai.Type.STRING
|
|
5555
|
+
},
|
|
5556
|
+
description: "List of artifact names to load"
|
|
5557
|
+
}
|
|
5545
5558
|
},
|
|
5546
|
-
|
|
5547
|
-
async (instance) => await instance.reinitialize(),
|
|
5548
|
-
_optionalChain([this, 'access', _149 => _149.config, 'access', _150 => _150.retryOptions, 'optionalAccess', _151 => _151.maxRetries]) || 2
|
|
5549
|
-
);
|
|
5550
|
-
return await wrappedCall();
|
|
5551
|
-
} catch (error) {
|
|
5552
|
-
if (!(error instanceof McpError)) {
|
|
5553
|
-
throw new McpError(
|
|
5554
|
-
`Error calling tool "${name}": ${error instanceof Error ? error.message : String(error)}`,
|
|
5555
|
-
"tool_execution_error" /* TOOL_EXECUTION_ERROR */,
|
|
5556
|
-
error instanceof Error ? error : void 0
|
|
5557
|
-
);
|
|
5559
|
+
required: []
|
|
5558
5560
|
}
|
|
5559
|
-
|
|
5560
|
-
}
|
|
5561
|
+
};
|
|
5561
5562
|
}
|
|
5562
5563
|
/**
|
|
5563
|
-
*
|
|
5564
|
-
* Should be called when the service is no longer needed.
|
|
5565
|
-
* Similar to Python's close() method.
|
|
5564
|
+
* Execute the load artifacts operation
|
|
5566
5565
|
*/
|
|
5567
|
-
async
|
|
5568
|
-
|
|
5569
|
-
|
|
5566
|
+
async runAsync(args, context4) {
|
|
5567
|
+
const artifactNames = args.artifact_names || [];
|
|
5568
|
+
return { artifact_names: artifactNames };
|
|
5570
5569
|
}
|
|
5571
5570
|
/**
|
|
5572
|
-
*
|
|
5571
|
+
* Processes the outgoing LLM request for this tool.
|
|
5573
5572
|
*/
|
|
5574
|
-
|
|
5575
|
-
|
|
5573
|
+
async processLlmRequest(toolContext, llmRequest) {
|
|
5574
|
+
await super.processLlmRequest(toolContext, llmRequest);
|
|
5575
|
+
await this.appendArtifactsToLlmRequest(toolContext, llmRequest);
|
|
5576
5576
|
}
|
|
5577
|
-
|
|
5578
|
-
|
|
5579
|
-
|
|
5580
|
-
|
|
5581
|
-
);
|
|
5582
|
-
return;
|
|
5583
|
-
}
|
|
5577
|
+
/**
|
|
5578
|
+
* Appends artifacts information to the LLM request
|
|
5579
|
+
*/
|
|
5580
|
+
async appendArtifactsToLlmRequest(toolContext, llmRequest) {
|
|
5584
5581
|
try {
|
|
5585
|
-
|
|
5586
|
-
|
|
5587
|
-
|
|
5588
|
-
|
|
5589
|
-
|
|
5590
|
-
|
|
5591
|
-
|
|
5592
|
-
|
|
5593
|
-
|
|
5594
|
-
|
|
5595
|
-
|
|
5596
|
-
|
|
5582
|
+
const artifactNames = await toolContext.listArtifacts();
|
|
5583
|
+
if (!artifactNames || artifactNames.length === 0) {
|
|
5584
|
+
return;
|
|
5585
|
+
}
|
|
5586
|
+
const instructions = [
|
|
5587
|
+
`You have a list of artifacts:
|
|
5588
|
+
${JSON.stringify(artifactNames)}
|
|
5589
|
+
|
|
5590
|
+
When the user asks questions about any of the artifacts, you should call the
|
|
5591
|
+
\`load_artifacts\` function to load the artifact. Do not generate any text other
|
|
5592
|
+
than the function call.
|
|
5593
|
+
`
|
|
5594
|
+
];
|
|
5595
|
+
if (llmRequest.appendInstructions) {
|
|
5596
|
+
llmRequest.appendInstructions(instructions);
|
|
5597
|
+
}
|
|
5598
|
+
if (llmRequest.contents && llmRequest.contents.length > 0) {
|
|
5599
|
+
const lastContent = llmRequest.contents[llmRequest.contents.length - 1];
|
|
5600
|
+
if (lastContent.parts && lastContent.parts.length > 0) {
|
|
5601
|
+
const firstPart = lastContent.parts[0];
|
|
5602
|
+
const functionResponse = this.extractFunctionResponse(firstPart);
|
|
5603
|
+
if (functionResponse && functionResponse.name === "load_artifacts") {
|
|
5604
|
+
const requestedArtifactNames = functionResponse.response.artifact_names || [];
|
|
5605
|
+
for (const artifactName of requestedArtifactNames) {
|
|
5606
|
+
try {
|
|
5607
|
+
const artifact = await toolContext.loadArtifact(artifactName);
|
|
5608
|
+
if (artifact) {
|
|
5609
|
+
llmRequest.contents.push({
|
|
5610
|
+
role: "user",
|
|
5611
|
+
parts: [
|
|
5612
|
+
{
|
|
5613
|
+
text: `Artifact ${artifactName} is:`
|
|
5614
|
+
},
|
|
5615
|
+
artifact
|
|
5616
|
+
]
|
|
5617
|
+
});
|
|
5618
|
+
}
|
|
5619
|
+
} catch (error) {
|
|
5620
|
+
console.error(
|
|
5621
|
+
`Failed to load artifact ${artifactName}:`,
|
|
5622
|
+
error
|
|
5623
|
+
);
|
|
5624
|
+
}
|
|
5597
5625
|
}
|
|
5598
|
-
throw new McpError(
|
|
5599
|
-
`Sampling request failed: ${error instanceof Error ? error.message : String(error)}`,
|
|
5600
|
-
"SAMPLING_ERROR" /* SAMPLING_ERROR */,
|
|
5601
|
-
error instanceof Error ? error : void 0
|
|
5602
|
-
);
|
|
5603
5626
|
}
|
|
5604
5627
|
}
|
|
5605
|
-
|
|
5606
|
-
this.logger.debug("\u{1F3AF} Sampling handler registered successfully");
|
|
5628
|
+
}
|
|
5607
5629
|
} catch (error) {
|
|
5608
|
-
|
|
5609
|
-
this.logger.debug(
|
|
5610
|
-
"\u26A0\uFE0F Sampling handler registration failed, continuing without sampling support"
|
|
5611
|
-
);
|
|
5612
|
-
}
|
|
5613
|
-
}
|
|
5614
|
-
/**
|
|
5615
|
-
* Set a new ADK sampling handler
|
|
5616
|
-
*/
|
|
5617
|
-
setSamplingHandler(handler) {
|
|
5618
|
-
this.mcpSamplingHandler = new McpSamplingHandler(handler);
|
|
5619
|
-
if (this.client) {
|
|
5620
|
-
this.setupSamplingHandler(this.client).catch((error) => {
|
|
5621
|
-
this.logger.error("Failed to update ADK sampling handler:", error);
|
|
5622
|
-
});
|
|
5630
|
+
console.error("Error appending artifacts to LLM request:", error);
|
|
5623
5631
|
}
|
|
5624
5632
|
}
|
|
5625
5633
|
/**
|
|
5626
|
-
*
|
|
5634
|
+
* Extracts function response from a part if it exists
|
|
5627
5635
|
*/
|
|
5628
|
-
|
|
5629
|
-
|
|
5630
|
-
|
|
5631
|
-
try {
|
|
5632
|
-
_optionalChain([this, 'access', _152 => _152.client, 'access', _153 => _153.removeRequestHandler, 'optionalCall', _154 => _154("sampling/createMessage")]);
|
|
5633
|
-
} catch (error) {
|
|
5634
|
-
this.logger.error("Failed to remove sampling handler:", error);
|
|
5635
|
-
}
|
|
5636
|
+
extractFunctionResponse(part) {
|
|
5637
|
+
if ("functionResponse" in part && part.functionResponse) {
|
|
5638
|
+
return part.functionResponse;
|
|
5636
5639
|
}
|
|
5640
|
+
return null;
|
|
5637
5641
|
}
|
|
5638
|
-
}
|
|
5642
|
+
};
|
|
5639
5643
|
|
|
5640
5644
|
// src/tools/mcp/create-tool.ts
|
|
5641
5645
|
init_logger();
|
|
@@ -6028,6 +6032,14 @@ function McpCoinGecko(config = {}) {
|
|
|
6028
6032
|
);
|
|
6029
6033
|
return new McpToolset(mcpConfig);
|
|
6030
6034
|
}
|
|
6035
|
+
function McpUpbit(config = {}) {
|
|
6036
|
+
const mcpConfig = createMcpConfig(
|
|
6037
|
+
"Upbit MCP Client",
|
|
6038
|
+
"@iqai/mcp-upbit",
|
|
6039
|
+
config
|
|
6040
|
+
);
|
|
6041
|
+
return new McpToolset(mcpConfig);
|
|
6042
|
+
}
|
|
6031
6043
|
function McpFilesystem(config = {}) {
|
|
6032
6044
|
const mcpConfig = createMcpConfig(
|
|
6033
6045
|
"Filesystem MCP Client",
|
|
@@ -13309,4 +13321,6 @@ var VERSION = "0.1.0";
|
|
|
13309
13321
|
|
|
13310
13322
|
|
|
13311
13323
|
|
|
13312
|
-
|
|
13324
|
+
|
|
13325
|
+
|
|
13326
|
+
exports.AF_FUNCTION_CALL_ID_PREFIX = AF_FUNCTION_CALL_ID_PREFIX; exports.Agent = LlmAgent; exports.AgentBuilder = AgentBuilder; exports.AgentEvaluator = AgentEvaluator; exports.AgentTool = AgentTool; exports.Agents = agents_exports; exports.AiSdkLlm = AiSdkLlm; exports.AnthropicLlm = AnthropicLlm; exports.ApiKeyCredential = ApiKeyCredential; exports.ApiKeyScheme = ApiKeyScheme; exports.AuthConfig = AuthConfig; exports.AuthCredential = AuthCredential; exports.AuthCredentialType = AuthCredentialType; exports.AuthHandler = AuthHandler; exports.AuthScheme = AuthScheme; exports.AuthSchemeType = AuthSchemeType; exports.AuthTool = AuthTool; exports.AutoFlow = AutoFlow; exports.BaseAgent = BaseAgent; exports.BaseCodeExecutor = BaseCodeExecutor; exports.BaseLLMConnection = BaseLLMConnection; exports.BaseLlm = BaseLlm; exports.BaseLlmFlow = BaseLlmFlow; exports.BaseLlmRequestProcessor = BaseLlmRequestProcessor; exports.BaseLlmResponseProcessor = BaseLlmResponseProcessor; exports.BasePlanner = BasePlanner; exports.BaseSessionService = BaseSessionService; exports.BaseTool = BaseTool; exports.BasicAuthCredential = BasicAuthCredential; exports.BearerTokenCredential = BearerTokenCredential; exports.BuiltInCodeExecutor = BuiltInCodeExecutor; exports.BuiltInPlanner = BuiltInPlanner; exports.CallbackContext = CallbackContext; exports.CodeExecutionUtils = CodeExecutionUtils; exports.CodeExecutorContext = CodeExecutorContext; exports.DatabaseSessionService = DatabaseSessionService; exports.EnhancedAuthConfig = EnhancedAuthConfig; exports.EvalResult = EvalResult; exports.EvalStatus = EvalStatus; exports.Evaluation = evaluation_exports; exports.Evaluator = Evaluator; exports.Event = Event; exports.EventActions = EventActions; exports.Events = events_exports; exports.ExitLoopTool = ExitLoopTool; exports.FileOperationsTool = FileOperationsTool; exports.FinalResponseMatchV2Evaluator = FinalResponseMatchV2Evaluator; exports.Flows = flows_exports; exports.FunctionTool = FunctionTool; exports.GcsArtifactService = GcsArtifactService; exports.GetUserChoiceTool = GetUserChoiceTool; exports.GoogleLlm = GoogleLlm; exports.GoogleSearch = GoogleSearch; exports.HttpRequestTool = HttpRequestTool; exports.HttpScheme = HttpScheme; exports.InMemoryArtifactService = InMemoryArtifactService; exports.InMemoryMemoryService = InMemoryMemoryService; exports.InMemoryRunner = InMemoryRunner; exports.InMemorySessionService = InMemorySessionService; exports.InvocationContext = InvocationContext; exports.LLMRegistry = LLMRegistry; exports.LangGraphAgent = LangGraphAgent; exports.LlmAgent = LlmAgent; exports.LlmCallsLimitExceededError = LlmCallsLimitExceededError; exports.LlmRequest = LlmRequest; exports.LlmResponse = LlmResponse; exports.LoadArtifactsTool = LoadArtifactsTool; exports.LoadMemoryTool = LoadMemoryTool; exports.LocalEvalService = LocalEvalService; exports.LoopAgent = LoopAgent; exports.McpAbi = McpAbi; exports.McpAtp = McpAtp; exports.McpBamm = McpBamm; exports.McpClientService = McpClientService; exports.McpCoinGecko = McpCoinGecko; exports.McpDiscord = McpDiscord; exports.McpError = McpError; exports.McpErrorType = McpErrorType; exports.McpFilesystem = McpFilesystem; exports.McpFraxlend = McpFraxlend; exports.McpGeneric = McpGeneric; exports.McpIqWiki = McpIqWiki; exports.McpMemory = McpMemory; exports.McpNearAgent = McpNearAgent; exports.McpNearIntents = McpNearIntents; exports.McpOdos = McpOdos; exports.McpSamplingHandler = McpSamplingHandler; exports.McpTelegram = McpTelegram; exports.McpToolset = McpToolset; exports.McpUpbit = McpUpbit; exports.Memory = memory_exports; exports.Models = models_exports; exports.OAuth2Credential = OAuth2Credential; exports.OAuth2Scheme = OAuth2Scheme; exports.OpenAiLlm = OpenAiLlm; exports.OpenIdConnectScheme = OpenIdConnectScheme; exports.ParallelAgent = ParallelAgent; exports.PlanReActPlanner = PlanReActPlanner; exports.PrebuiltMetrics = PrebuiltMetrics; exports.REQUEST_EUC_FUNCTION_CALL_NAME = REQUEST_EUC_FUNCTION_CALL_NAME; exports.ReadonlyContext = ReadonlyContext; exports.RougeEvaluator = RougeEvaluator; exports.RunConfig = RunConfig; exports.Runner = Runner; exports.SafetyEvaluatorV1 = SafetyEvaluatorV1; exports.SequentialAgent = SequentialAgent; exports.Sessions = sessions_exports; exports.SingleFlow = SingleFlow; exports.State = State; exports.StreamingMode = StreamingMode; exports.TelemetryService = TelemetryService; exports.ToolContext = ToolContext; exports.Tools = tools_exports; exports.TrajectoryEvaluator = TrajectoryEvaluator; exports.TransferToAgentTool = TransferToAgentTool; exports.UserInteractionTool = UserInteractionTool; exports.VERSION = VERSION; exports.VertexAiSessionService = VertexAiSessionService; exports._findFunctionCallEventIfLastEventIsFunctionResponse = _findFunctionCallEventIfLastEventIsFunctionResponse; exports.adkToMcpToolType = adkToMcpToolType; exports.agentTransferRequestProcessor = requestProcessor8; exports.basicRequestProcessor = requestProcessor2; exports.buildFunctionDeclaration = buildFunctionDeclaration; exports.codeExecutionRequestProcessor = requestProcessor3; exports.codeExecutionResponseProcessor = responseProcessor; exports.contentRequestProcessor = requestProcessor4; exports.createAuthToolArguments = createAuthToolArguments; exports.createBranchContextForSubAgent = createBranchContextForSubAgent; exports.createDatabaseSessionService = createDatabaseSessionService; exports.createFunctionTool = createFunctionTool; exports.createMysqlSessionService = createMysqlSessionService; exports.createPostgresSessionService = createPostgresSessionService; exports.createSamplingHandler = createSamplingHandler; exports.createSqliteSessionService = createSqliteSessionService; exports.createTool = createTool; exports.generateAuthEvent = generateAuthEvent; exports.generateClientFunctionCallId = generateClientFunctionCallId; exports.getLongRunningFunctionCalls = getLongRunningFunctionCalls; exports.getMcpTools = getMcpTools; exports.handleFunctionCallsAsync = handleFunctionCallsAsync; exports.handleFunctionCallsLive = handleFunctionCallsLive; exports.identityRequestProcessor = requestProcessor5; exports.initializeTelemetry = initializeTelemetry; exports.injectSessionState = injectSessionState; exports.instructionsRequestProcessor = requestProcessor6; exports.isEnhancedAuthConfig = isEnhancedAuthConfig; exports.jsonSchemaToDeclaration = jsonSchemaToDeclaration; exports.mcpSchemaToParameters = mcpSchemaToParameters; exports.mergeAgentRun = mergeAgentRun; exports.mergeParallelFunctionResponseEvents = mergeParallelFunctionResponseEvents; exports.newInvocationContextId = newInvocationContextId; exports.nlPlanningRequestProcessor = requestProcessor7; exports.nlPlanningResponseProcessor = responseProcessor2; exports.normalizeJsonSchema = normalizeJsonSchema; exports.populateClientFunctionCallId = populateClientFunctionCallId; exports.registerProviders = registerProviders; exports.removeClientFunctionCallId = removeClientFunctionCallId; exports.requestProcessor = requestProcessor; exports.shutdownTelemetry = shutdownTelemetry; exports.telemetryService = telemetryService; exports.traceLlmCall = traceLlmCall; exports.traceToolCall = traceToolCall; exports.tracer = tracer;
|