@paean-ai/adk 0.2.19 → 0.2.20
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/dist/cjs/agents/active_streaming_tool.js +44 -0
- package/dist/cjs/agents/base_agent.js +245 -0
- package/dist/cjs/agents/base_llm_processor.js +44 -0
- package/dist/cjs/agents/callback_context.js +98 -0
- package/dist/cjs/agents/content_processor_utils.js +311 -0
- package/dist/cjs/agents/functions.js +425 -0
- package/dist/cjs/agents/instructions.js +110 -0
- package/dist/cjs/agents/invocation_context.js +107 -0
- package/dist/cjs/agents/live_request_queue.js +136 -0
- package/dist/cjs/agents/llm_agent.js +1257 -0
- package/dist/cjs/agents/loop_agent.js +68 -0
- package/dist/cjs/agents/parallel_agent.js +78 -0
- package/dist/cjs/agents/readonly_context.js +68 -0
- package/dist/cjs/agents/run_config.js +70 -0
- package/dist/cjs/agents/sequential_agent.js +84 -0
- package/dist/cjs/agents/transcription_entry.js +27 -0
- package/dist/cjs/artifacts/base_artifact_service.js +27 -0
- package/dist/cjs/artifacts/gcs_artifact_service.js +140 -0
- package/dist/cjs/artifacts/in_memory_artifact_service.js +119 -0
- package/dist/cjs/auth/auth_credential.js +46 -0
- package/dist/cjs/auth/auth_handler.js +92 -0
- package/dist/cjs/auth/auth_schemes.js +62 -0
- package/dist/cjs/auth/auth_tool.js +27 -0
- package/dist/cjs/auth/credential_service/base_credential_service.js +27 -0
- package/dist/cjs/auth/credential_service/in_memory_credential_service.js +63 -0
- package/dist/cjs/auth/exchanger/base_credential_exchanger.js +40 -0
- package/dist/cjs/auth/exchanger/credential_exchanger_registry.js +59 -0
- package/dist/cjs/code_executors/base_code_executor.js +76 -0
- package/dist/cjs/code_executors/built_in_code_executor.js +58 -0
- package/dist/cjs/code_executors/code_execution_utils.js +142 -0
- package/dist/cjs/code_executors/code_executor_context.js +198 -0
- package/dist/cjs/common.js +181 -0
- package/dist/cjs/events/event.js +119 -0
- package/dist/cjs/events/event_actions.js +83 -0
- package/dist/cjs/examples/base_example_provider.js +40 -0
- package/dist/cjs/examples/example.js +27 -0
- package/dist/cjs/examples/example_util.js +107 -0
- package/dist/cjs/index.js +12 -12
- package/dist/cjs/index.js.map +3 -3
- package/dist/cjs/index_web.js +33 -0
- package/dist/cjs/memory/base_memory_service.js +27 -0
- package/dist/cjs/memory/in_memory_memory_service.js +97 -0
- package/dist/cjs/memory/memory_entry.js +27 -0
- package/dist/cjs/models/base_llm.js +95 -0
- package/dist/cjs/models/base_llm_connection.js +27 -0
- package/dist/cjs/models/gemini_llm_connection.js +132 -0
- package/dist/cjs/models/google_llm.js +472 -0
- package/dist/cjs/models/llm_request.js +82 -0
- package/dist/cjs/models/llm_response.js +71 -0
- package/dist/cjs/models/registry.js +121 -0
- package/dist/cjs/plugins/base_plugin.js +236 -0
- package/dist/cjs/plugins/logging_plugin.js +222 -0
- package/dist/cjs/plugins/plugin_manager.js +239 -0
- package/dist/cjs/plugins/security_plugin.js +153 -0
- package/dist/cjs/runner/in_memory_runner.js +58 -0
- package/dist/cjs/runner/runner.js +277 -0
- package/dist/cjs/sessions/base_session_service.js +71 -0
- package/dist/cjs/sessions/in_memory_session_service.js +184 -0
- package/dist/cjs/sessions/session.js +48 -0
- package/dist/cjs/sessions/state.js +101 -0
- package/dist/cjs/telemetry/google_cloud.js +85 -0
- package/dist/cjs/telemetry/setup.js +97 -0
- package/dist/cjs/telemetry/tracing.js +231 -0
- package/dist/cjs/tools/agent_tool.js +134 -0
- package/dist/cjs/tools/base_tool.js +107 -0
- package/dist/cjs/tools/base_toolset.js +76 -0
- package/dist/cjs/tools/forwarding_artifact_service.js +71 -0
- package/dist/cjs/tools/function_tool.js +101 -0
- package/dist/cjs/tools/google_search_tool.js +77 -0
- package/dist/cjs/tools/long_running_tool.js +63 -0
- package/dist/cjs/tools/mcp/mcp_session_manager.js +65 -0
- package/dist/cjs/tools/mcp/mcp_tool.js +65 -0
- package/dist/cjs/tools/mcp/mcp_toolset.js +61 -0
- package/dist/cjs/tools/tool_confirmation.js +49 -0
- package/dist/cjs/tools/tool_context.js +129 -0
- package/dist/cjs/utils/client_labels.js +56 -0
- package/dist/cjs/utils/deep_clone.js +44 -0
- package/dist/cjs/utils/env_aware_utils.js +83 -0
- package/dist/cjs/utils/gemini_schema_util.js +88 -0
- package/dist/cjs/utils/logger.js +121 -0
- package/dist/cjs/utils/model_name.js +76 -0
- package/dist/cjs/utils/simple_zod_to_json.js +191 -0
- package/dist/cjs/utils/variant_utils.js +55 -0
- package/dist/cjs/version.js +39 -0
- package/dist/esm/agents/active_streaming_tool.js +14 -0
- package/dist/esm/agents/base_agent.js +214 -0
- package/dist/esm/agents/base_llm_processor.js +13 -0
- package/dist/esm/agents/callback_context.js +68 -0
- package/dist/esm/agents/content_processor_utils.js +280 -0
- package/dist/esm/agents/functions.js +384 -0
- package/dist/esm/agents/instructions.js +80 -0
- package/dist/esm/agents/invocation_context.js +76 -0
- package/dist/esm/agents/live_request_queue.js +106 -0
- package/dist/esm/agents/llm_agent.js +1225 -0
- package/dist/esm/agents/loop_agent.js +38 -0
- package/dist/esm/agents/parallel_agent.js +48 -0
- package/dist/esm/agents/readonly_context.js +38 -0
- package/dist/esm/agents/run_config.js +39 -0
- package/dist/esm/agents/sequential_agent.js +54 -0
- package/dist/esm/agents/transcription_entry.js +5 -0
- package/dist/esm/artifacts/base_artifact_service.js +5 -0
- package/dist/esm/artifacts/gcs_artifact_service.js +110 -0
- package/dist/esm/artifacts/in_memory_artifact_service.js +89 -0
- package/dist/esm/auth/auth_credential.js +16 -0
- package/dist/esm/auth/auth_handler.js +62 -0
- package/dist/esm/auth/auth_schemes.js +31 -0
- package/dist/esm/auth/auth_tool.js +5 -0
- package/dist/esm/auth/credential_service/base_credential_service.js +5 -0
- package/dist/esm/auth/credential_service/in_memory_credential_service.js +33 -0
- package/dist/esm/auth/exchanger/base_credential_exchanger.js +10 -0
- package/dist/esm/auth/exchanger/credential_exchanger_registry.js +29 -0
- package/dist/esm/code_executors/base_code_executor.js +46 -0
- package/dist/esm/code_executors/built_in_code_executor.js +28 -0
- package/dist/esm/code_executors/code_execution_utils.js +108 -0
- package/dist/esm/code_executors/code_executor_context.js +168 -0
- package/dist/esm/common.js +98 -0
- package/dist/esm/events/event.js +83 -0
- package/dist/esm/events/event_actions.js +52 -0
- package/dist/esm/examples/base_example_provider.js +10 -0
- package/dist/esm/examples/example.js +5 -0
- package/dist/esm/examples/example_util.js +76 -0
- package/dist/esm/index.js +12 -12
- package/dist/esm/index.js.map +3 -3
- package/dist/esm/index_web.js +6 -0
- package/dist/esm/memory/base_memory_service.js +5 -0
- package/dist/esm/memory/in_memory_memory_service.js +67 -0
- package/dist/esm/memory/memory_entry.js +5 -0
- package/dist/esm/models/base_llm.js +64 -0
- package/dist/esm/models/base_llm_connection.js +5 -0
- package/dist/esm/models/gemini_llm_connection.js +102 -0
- package/dist/esm/models/google_llm.js +446 -0
- package/dist/esm/models/llm_request.js +50 -0
- package/dist/esm/models/llm_response.js +41 -0
- package/dist/esm/models/registry.js +91 -0
- package/dist/esm/plugins/base_plugin.js +206 -0
- package/dist/esm/plugins/logging_plugin.js +192 -0
- package/dist/esm/plugins/plugin_manager.js +209 -0
- package/dist/esm/plugins/security_plugin.js +119 -0
- package/dist/esm/runner/in_memory_runner.js +28 -0
- package/dist/esm/runner/runner.js +247 -0
- package/dist/esm/sessions/base_session_service.js +41 -0
- package/dist/esm/sessions/in_memory_session_service.js +154 -0
- package/dist/esm/sessions/session.js +18 -0
- package/dist/esm/sessions/state.js +71 -0
- package/dist/esm/telemetry/google_cloud.js +54 -0
- package/dist/esm/telemetry/setup.js +67 -0
- package/dist/esm/telemetry/tracing.js +195 -0
- package/dist/esm/tools/agent_tool.js +104 -0
- package/dist/esm/tools/base_tool.js +77 -0
- package/dist/esm/tools/base_toolset.js +46 -0
- package/dist/esm/tools/forwarding_artifact_service.js +41 -0
- package/dist/esm/tools/function_tool.js +71 -0
- package/dist/esm/tools/google_search_tool.js +47 -0
- package/dist/esm/tools/long_running_tool.js +33 -0
- package/dist/esm/tools/mcp/mcp_session_manager.js +35 -0
- package/dist/esm/tools/mcp/mcp_tool.js +35 -0
- package/dist/esm/tools/mcp/mcp_toolset.js +31 -0
- package/dist/esm/tools/tool_confirmation.js +19 -0
- package/dist/esm/tools/tool_context.js +99 -0
- package/dist/esm/utils/client_labels.js +26 -0
- package/dist/esm/utils/deep_clone.js +14 -0
- package/dist/esm/utils/env_aware_utils.js +49 -0
- package/dist/esm/utils/gemini_schema_util.js +58 -0
- package/dist/esm/utils/logger.js +89 -0
- package/dist/esm/utils/model_name.js +41 -0
- package/dist/esm/utils/simple_zod_to_json.js +160 -0
- package/dist/esm/utils/variant_utils.js +24 -0
- package/dist/esm/version.js +9 -0
- package/dist/types/models/google_llm.d.ts +0 -7
- package/dist/web/agents/active_streaming_tool.js +14 -0
- package/dist/web/agents/base_agent.js +265 -0
- package/dist/web/agents/base_llm_processor.js +13 -0
- package/dist/web/agents/callback_context.js +68 -0
- package/dist/web/agents/content_processor_utils.js +280 -0
- package/dist/web/agents/functions.js +384 -0
- package/dist/web/agents/instructions.js +80 -0
- package/dist/web/agents/invocation_context.js +76 -0
- package/dist/web/agents/live_request_queue.js +124 -0
- package/dist/web/agents/llm_agent.js +1355 -0
- package/dist/web/agents/loop_agent.js +71 -0
- package/dist/web/agents/parallel_agent.js +83 -0
- package/dist/web/agents/readonly_context.js +38 -0
- package/dist/web/agents/run_config.js +54 -0
- package/dist/web/agents/sequential_agent.js +99 -0
- package/dist/web/agents/transcription_entry.js +5 -0
- package/dist/web/artifacts/base_artifact_service.js +5 -0
- package/dist/web/artifacts/gcs_artifact_service.js +126 -0
- package/dist/web/artifacts/in_memory_artifact_service.js +89 -0
- package/dist/web/auth/auth_credential.js +16 -0
- package/dist/web/auth/auth_handler.js +62 -0
- package/dist/web/auth/auth_schemes.js +31 -0
- package/dist/web/auth/auth_tool.js +5 -0
- package/dist/web/auth/credential_service/base_credential_service.js +5 -0
- package/dist/web/auth/credential_service/in_memory_credential_service.js +33 -0
- package/dist/web/auth/exchanger/base_credential_exchanger.js +10 -0
- package/dist/web/auth/exchanger/credential_exchanger_registry.js +29 -0
- package/dist/web/code_executors/base_code_executor.js +46 -0
- package/dist/web/code_executors/built_in_code_executor.js +28 -0
- package/dist/web/code_executors/code_execution_utils.js +105 -0
- package/dist/web/code_executors/code_executor_context.js +168 -0
- package/dist/web/common.js +98 -0
- package/dist/web/events/event.js +101 -0
- package/dist/web/events/event_actions.js +67 -0
- package/dist/web/examples/base_example_provider.js +10 -0
- package/dist/web/examples/example.js +5 -0
- package/dist/web/examples/example_util.js +75 -0
- package/dist/web/index.js +1 -1
- package/dist/web/index.js.map +3 -3
- package/dist/web/index_web.js +6 -0
- package/dist/web/memory/base_memory_service.js +5 -0
- package/dist/web/memory/in_memory_memory_service.js +67 -0
- package/dist/web/memory/memory_entry.js +5 -0
- package/dist/web/models/base_llm.js +64 -0
- package/dist/web/models/base_llm_connection.js +5 -0
- package/dist/web/models/gemini_llm_connection.js +120 -0
- package/dist/web/models/google_llm.js +487 -0
- package/dist/web/models/llm_request.js +50 -0
- package/dist/web/models/llm_response.js +41 -0
- package/dist/web/models/registry.js +91 -0
- package/dist/web/plugins/base_plugin.js +206 -0
- package/dist/web/plugins/logging_plugin.js +192 -0
- package/dist/web/plugins/plugin_manager.js +209 -0
- package/dist/web/plugins/security_plugin.js +119 -0
- package/dist/web/runner/in_memory_runner.js +28 -0
- package/dist/web/runner/runner.js +278 -0
- package/dist/web/sessions/base_session_service.js +41 -0
- package/dist/web/sessions/in_memory_session_service.js +154 -0
- package/dist/web/sessions/session.js +18 -0
- package/dist/web/sessions/state.js +87 -0
- package/dist/web/telemetry/google_cloud.js +54 -0
- package/dist/web/telemetry/setup.js +67 -0
- package/dist/web/telemetry/tracing.js +210 -0
- package/dist/web/tools/agent_tool.js +118 -0
- package/dist/web/tools/base_tool.js +77 -0
- package/dist/web/tools/base_toolset.js +46 -0
- package/dist/web/tools/forwarding_artifact_service.js +41 -0
- package/dist/web/tools/function_tool.js +71 -0
- package/dist/web/tools/google_search_tool.js +47 -0
- package/dist/web/tools/long_running_tool.js +50 -0
- package/dist/web/tools/mcp/mcp_session_manager.js +35 -0
- package/dist/web/tools/mcp/mcp_tool.js +35 -0
- package/dist/web/tools/mcp/mcp_toolset.js +31 -0
- package/dist/web/tools/tool_confirmation.js +19 -0
- package/dist/web/tools/tool_context.js +99 -0
- package/dist/web/utils/client_labels.js +26 -0
- package/dist/web/utils/deep_clone.js +14 -0
- package/dist/web/utils/env_aware_utils.js +49 -0
- package/dist/web/utils/gemini_schema_util.js +58 -0
- package/dist/web/utils/logger.js +89 -0
- package/dist/web/utils/model_name.js +41 -0
- package/dist/web/utils/simple_zod_to_json.js +174 -0
- package/dist/web/utils/variant_utils.js +24 -0
- package/dist/web/version.js +9 -0
- package/package.json +1 -1
|
@@ -0,0 +1,1225 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2025 Google LLC
|
|
4
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
5
|
+
*/
|
|
6
|
+
import { z } from "zod";
|
|
7
|
+
import { BaseCodeExecutor } from "../code_executors/base_code_executor.js";
|
|
8
|
+
import { BuiltInCodeExecutor } from "../code_executors/built_in_code_executor.js";
|
|
9
|
+
import { buildCodeExecutionResultPart, buildExecutableCodePart, convertCodeExecutionParts, extractCodeAndTruncateContent } from "../code_executors/code_execution_utils.js";
|
|
10
|
+
import { CodeExecutorContext } from "../code_executors/code_executor_context.js";
|
|
11
|
+
import { createEvent, createNewEventId, getFunctionCalls, getFunctionResponses, isFinalResponse } from "../events/event.js";
|
|
12
|
+
import { createEventActions } from "../events/event_actions.js";
|
|
13
|
+
import { isBaseLlm } from "../models/base_llm.js";
|
|
14
|
+
import { appendInstructions, setOutputSchema } from "../models/llm_request.js";
|
|
15
|
+
import { LLMRegistry } from "../models/registry.js";
|
|
16
|
+
import { State } from "../sessions/state.js";
|
|
17
|
+
import { BaseTool } from "../tools/base_tool.js";
|
|
18
|
+
import { FunctionTool } from "../tools/function_tool.js";
|
|
19
|
+
import { ToolConfirmation } from "../tools/tool_confirmation.js";
|
|
20
|
+
import { ToolContext } from "../tools/tool_context.js";
|
|
21
|
+
import { deepClone } from "../utils/deep_clone.js";
|
|
22
|
+
import { base64Decode } from "../utils/env_aware_utils.js";
|
|
23
|
+
import { logger } from "../utils/logger.js";
|
|
24
|
+
import { BaseAgent } from "./base_agent.js";
|
|
25
|
+
import { BaseLlmRequestProcessor } from "./base_llm_processor.js";
|
|
26
|
+
import { CallbackContext } from "./callback_context.js";
|
|
27
|
+
import { getContents, getCurrentTurnContents } from "./content_processor_utils.js";
|
|
28
|
+
import { generateAuthEvent, generateRequestConfirmationEvent, getLongRunningFunctionCalls, handleFunctionCallList, handleFunctionCallsAsync, populateClientFunctionCallId, REQUEST_CONFIRMATION_FUNCTION_CALL_NAME } from "./functions.js";
|
|
29
|
+
import { injectSessionState } from "./instructions.js";
|
|
30
|
+
import { ReadonlyContext } from "./readonly_context.js";
|
|
31
|
+
import { StreamingMode } from "./run_config.js";
|
|
32
|
+
const ADK_AGENT_NAME_LABEL_KEY = "adk_agent_name";
|
|
33
|
+
async function convertToolUnionToTools(toolUnion, context) {
|
|
34
|
+
if (toolUnion instanceof BaseTool) {
|
|
35
|
+
return [toolUnion];
|
|
36
|
+
}
|
|
37
|
+
return await toolUnion.getTools(context);
|
|
38
|
+
}
|
|
39
|
+
class BasicLlmRequestProcessor extends BaseLlmRequestProcessor {
|
|
40
|
+
async *runAsync(invocationContext, llmRequest) {
|
|
41
|
+
var _a;
|
|
42
|
+
const agent = invocationContext.agent;
|
|
43
|
+
if (!(agent instanceof LlmAgent)) {
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
llmRequest.model = agent.canonicalModel.model;
|
|
47
|
+
llmRequest.config = { ...(_a = agent.generateContentConfig) != null ? _a : {} };
|
|
48
|
+
if (agent.outputSchema) {
|
|
49
|
+
setOutputSchema(llmRequest, agent.outputSchema);
|
|
50
|
+
}
|
|
51
|
+
if (invocationContext.runConfig) {
|
|
52
|
+
llmRequest.liveConnectConfig.responseModalities = invocationContext.runConfig.responseModalities;
|
|
53
|
+
llmRequest.liveConnectConfig.speechConfig = invocationContext.runConfig.speechConfig;
|
|
54
|
+
llmRequest.liveConnectConfig.outputAudioTranscription = invocationContext.runConfig.outputAudioTranscription;
|
|
55
|
+
llmRequest.liveConnectConfig.inputAudioTranscription = invocationContext.runConfig.inputAudioTranscription;
|
|
56
|
+
llmRequest.liveConnectConfig.realtimeInputConfig = invocationContext.runConfig.realtimeInputConfig;
|
|
57
|
+
llmRequest.liveConnectConfig.enableAffectiveDialog = invocationContext.runConfig.enableAffectiveDialog;
|
|
58
|
+
llmRequest.liveConnectConfig.proactivity = invocationContext.runConfig.proactivity;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
const BASIC_LLM_REQUEST_PROCESSOR = new BasicLlmRequestProcessor();
|
|
63
|
+
class IdentityLlmRequestProcessor extends BaseLlmRequestProcessor {
|
|
64
|
+
async *runAsync(invocationContext, llmRequest) {
|
|
65
|
+
const agent = invocationContext.agent;
|
|
66
|
+
const si = [`You are an agent. Your internal name is "${agent.name}".`];
|
|
67
|
+
if (agent.description) {
|
|
68
|
+
si.push(`The description about you is "${agent.description}"`);
|
|
69
|
+
}
|
|
70
|
+
appendInstructions(llmRequest, si);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
const IDENTITY_LLM_REQUEST_PROCESSOR = new IdentityLlmRequestProcessor();
|
|
74
|
+
class InstructionsLlmRequestProcessor extends BaseLlmRequestProcessor {
|
|
75
|
+
/**
|
|
76
|
+
* Handles instructions and global instructions for LLM flow.
|
|
77
|
+
*/
|
|
78
|
+
async *runAsync(invocationContext, llmRequest) {
|
|
79
|
+
const agent = invocationContext.agent;
|
|
80
|
+
if (!(agent instanceof LlmAgent) || !(agent.rootAgent instanceof LlmAgent)) {
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
const rootAgent = agent.rootAgent;
|
|
84
|
+
if (rootAgent instanceof LlmAgent && rootAgent.globalInstruction) {
|
|
85
|
+
const { instruction, requireStateInjection } = await rootAgent.canonicalGlobalInstruction(
|
|
86
|
+
new ReadonlyContext(invocationContext)
|
|
87
|
+
);
|
|
88
|
+
let instructionWithState = instruction;
|
|
89
|
+
if (requireStateInjection) {
|
|
90
|
+
instructionWithState = await injectSessionState(
|
|
91
|
+
instruction,
|
|
92
|
+
new ReadonlyContext(invocationContext)
|
|
93
|
+
);
|
|
94
|
+
}
|
|
95
|
+
appendInstructions(llmRequest, [instructionWithState]);
|
|
96
|
+
}
|
|
97
|
+
if (agent.instruction) {
|
|
98
|
+
const { instruction, requireStateInjection } = await agent.canonicalInstruction(
|
|
99
|
+
new ReadonlyContext(invocationContext)
|
|
100
|
+
);
|
|
101
|
+
let instructionWithState = instruction;
|
|
102
|
+
if (requireStateInjection) {
|
|
103
|
+
instructionWithState = await injectSessionState(
|
|
104
|
+
instruction,
|
|
105
|
+
new ReadonlyContext(invocationContext)
|
|
106
|
+
);
|
|
107
|
+
}
|
|
108
|
+
appendInstructions(llmRequest, [instructionWithState]);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
const INSTRUCTIONS_LLM_REQUEST_PROCESSOR = new InstructionsLlmRequestProcessor();
|
|
113
|
+
class ContentRequestProcessor {
|
|
114
|
+
async *runAsync(invocationContext, llmRequest) {
|
|
115
|
+
const agent = invocationContext.agent;
|
|
116
|
+
if (!agent || !(agent instanceof LlmAgent)) {
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
if (agent.includeContents === "default") {
|
|
120
|
+
llmRequest.contents = getContents(
|
|
121
|
+
invocationContext.session.events,
|
|
122
|
+
agent.name,
|
|
123
|
+
invocationContext.branch
|
|
124
|
+
);
|
|
125
|
+
} else {
|
|
126
|
+
llmRequest.contents = getCurrentTurnContents(
|
|
127
|
+
invocationContext.session.events,
|
|
128
|
+
agent.name,
|
|
129
|
+
invocationContext.branch
|
|
130
|
+
);
|
|
131
|
+
}
|
|
132
|
+
return;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
const CONTENT_REQUEST_PROCESSOR = new ContentRequestProcessor();
|
|
136
|
+
class AgentTransferLlmRequestProcessor extends BaseLlmRequestProcessor {
|
|
137
|
+
constructor() {
|
|
138
|
+
super(...arguments);
|
|
139
|
+
this.toolName = "transfer_to_agent";
|
|
140
|
+
this.tool = new FunctionTool({
|
|
141
|
+
name: this.toolName,
|
|
142
|
+
description: "Transfer the question to another agent. This tool hands off control to another agent when it is more suitable to answer the user question according to the agent description.",
|
|
143
|
+
parameters: z.object({
|
|
144
|
+
agentName: z.string().describe("the agent name to transfer to.")
|
|
145
|
+
}),
|
|
146
|
+
execute: function(args, toolContext) {
|
|
147
|
+
if (!toolContext) {
|
|
148
|
+
throw new Error("toolContext is required.");
|
|
149
|
+
}
|
|
150
|
+
toolContext.actions.transferToAgent = args.agentName;
|
|
151
|
+
return "Transfer queued";
|
|
152
|
+
}
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
async *runAsync(invocationContext, llmRequest) {
|
|
156
|
+
if (!(invocationContext.agent instanceof LlmAgent)) {
|
|
157
|
+
return;
|
|
158
|
+
}
|
|
159
|
+
const transferTargets = this.getTransferTargets(invocationContext.agent);
|
|
160
|
+
if (!transferTargets.length) {
|
|
161
|
+
return;
|
|
162
|
+
}
|
|
163
|
+
appendInstructions(llmRequest, [
|
|
164
|
+
this.buildTargetAgentsInstructions(
|
|
165
|
+
invocationContext.agent,
|
|
166
|
+
transferTargets
|
|
167
|
+
)
|
|
168
|
+
]);
|
|
169
|
+
const toolContext = new ToolContext({ invocationContext });
|
|
170
|
+
await this.tool.processLlmRequest({ toolContext, llmRequest });
|
|
171
|
+
}
|
|
172
|
+
buildTargetAgentsInfo(targetAgent) {
|
|
173
|
+
return `
|
|
174
|
+
Agent name: ${targetAgent.name}
|
|
175
|
+
Agent description: ${targetAgent.description}
|
|
176
|
+
`;
|
|
177
|
+
}
|
|
178
|
+
buildTargetAgentsInstructions(agent, targetAgents) {
|
|
179
|
+
let instructions = `
|
|
180
|
+
You have a list of other agents to transfer to:
|
|
181
|
+
|
|
182
|
+
${targetAgents.map(this.buildTargetAgentsInfo).join("\n")}
|
|
183
|
+
|
|
184
|
+
If you are the best to answer the question according to your description, you
|
|
185
|
+
can answer it.
|
|
186
|
+
|
|
187
|
+
If another agent is better for answering the question according to its
|
|
188
|
+
description, call \`${this.toolName}\` function to transfer the
|
|
189
|
+
question to that agent. When transferring, do not generate any text other than
|
|
190
|
+
the function call.
|
|
191
|
+
`;
|
|
192
|
+
if (agent.parentAgent && !agent.disallowTransferToParent) {
|
|
193
|
+
instructions += `
|
|
194
|
+
Your parent agent is ${agent.parentAgent.name}. If neither the other agents nor
|
|
195
|
+
you are best for answering the question according to the descriptions, transfer
|
|
196
|
+
to your parent agent.
|
|
197
|
+
`;
|
|
198
|
+
}
|
|
199
|
+
return instructions;
|
|
200
|
+
}
|
|
201
|
+
getTransferTargets(agent) {
|
|
202
|
+
const targets = [];
|
|
203
|
+
targets.push(...agent.subAgents);
|
|
204
|
+
if (!agent.parentAgent || !(agent.parentAgent instanceof LlmAgent)) {
|
|
205
|
+
return targets;
|
|
206
|
+
}
|
|
207
|
+
if (!agent.disallowTransferToParent) {
|
|
208
|
+
targets.push(agent.parentAgent);
|
|
209
|
+
}
|
|
210
|
+
if (!agent.disallowTransferToPeers) {
|
|
211
|
+
targets.push(
|
|
212
|
+
...agent.parentAgent.subAgents.filter(
|
|
213
|
+
(peerAgent) => peerAgent.name !== agent.name
|
|
214
|
+
)
|
|
215
|
+
);
|
|
216
|
+
}
|
|
217
|
+
return targets;
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
const AGENT_TRANSFER_LLM_REQUEST_PROCESSOR = new AgentTransferLlmRequestProcessor();
|
|
221
|
+
class RequestConfirmationLlmRequestProcessor extends BaseLlmRequestProcessor {
|
|
222
|
+
/** Handles tool confirmation information to build the LLM request. */
|
|
223
|
+
async *runAsync(invocationContext, llmRequest) {
|
|
224
|
+
const agent = invocationContext.agent;
|
|
225
|
+
if (!(agent instanceof LlmAgent)) {
|
|
226
|
+
return;
|
|
227
|
+
}
|
|
228
|
+
const events = invocationContext.session.events;
|
|
229
|
+
if (!events || events.length === 0) {
|
|
230
|
+
return;
|
|
231
|
+
}
|
|
232
|
+
const requestConfirmationFunctionResponses = {};
|
|
233
|
+
let confirmationEventIndex = -1;
|
|
234
|
+
for (let i = events.length - 1; i >= 0; i--) {
|
|
235
|
+
const event = events[i];
|
|
236
|
+
if (event.author !== "user") {
|
|
237
|
+
continue;
|
|
238
|
+
}
|
|
239
|
+
const responses = getFunctionResponses(event);
|
|
240
|
+
if (!responses) {
|
|
241
|
+
continue;
|
|
242
|
+
}
|
|
243
|
+
let foundConfirmation = false;
|
|
244
|
+
for (const functionResponse of responses) {
|
|
245
|
+
if (functionResponse.name !== REQUEST_CONFIRMATION_FUNCTION_CALL_NAME) {
|
|
246
|
+
continue;
|
|
247
|
+
}
|
|
248
|
+
foundConfirmation = true;
|
|
249
|
+
let toolConfirmation = null;
|
|
250
|
+
if (functionResponse.response && Object.keys(functionResponse.response).length === 1 && "response" in functionResponse.response) {
|
|
251
|
+
toolConfirmation = JSON.parse(functionResponse.response["response"]);
|
|
252
|
+
} else if (functionResponse.response) {
|
|
253
|
+
toolConfirmation = new ToolConfirmation({
|
|
254
|
+
hint: functionResponse.response["hint"],
|
|
255
|
+
payload: functionResponse.response["payload"],
|
|
256
|
+
confirmed: functionResponse.response["confirmed"]
|
|
257
|
+
});
|
|
258
|
+
}
|
|
259
|
+
if (functionResponse.id && toolConfirmation) {
|
|
260
|
+
requestConfirmationFunctionResponses[functionResponse.id] = toolConfirmation;
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
if (foundConfirmation) {
|
|
264
|
+
confirmationEventIndex = i;
|
|
265
|
+
break;
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
if (Object.keys(requestConfirmationFunctionResponses).length === 0) {
|
|
269
|
+
return;
|
|
270
|
+
}
|
|
271
|
+
for (let i = confirmationEventIndex - 1; i >= 0; i--) {
|
|
272
|
+
const event = events[i];
|
|
273
|
+
const functionCalls = getFunctionCalls(event);
|
|
274
|
+
if (!functionCalls) {
|
|
275
|
+
continue;
|
|
276
|
+
}
|
|
277
|
+
const toolsToResumeWithConfirmation = {};
|
|
278
|
+
const toolsToResumeWithArgs = {};
|
|
279
|
+
for (const functionCall of functionCalls) {
|
|
280
|
+
if (!functionCall.id || !(functionCall.id in requestConfirmationFunctionResponses)) {
|
|
281
|
+
continue;
|
|
282
|
+
}
|
|
283
|
+
const args = functionCall.args;
|
|
284
|
+
if (!args || !("originalFunctionCall" in args)) {
|
|
285
|
+
continue;
|
|
286
|
+
}
|
|
287
|
+
const originalFunctionCall = args["originalFunctionCall"];
|
|
288
|
+
if (originalFunctionCall.id) {
|
|
289
|
+
toolsToResumeWithConfirmation[originalFunctionCall.id] = requestConfirmationFunctionResponses[functionCall.id];
|
|
290
|
+
toolsToResumeWithArgs[originalFunctionCall.id] = originalFunctionCall;
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
if (Object.keys(toolsToResumeWithConfirmation).length === 0) {
|
|
294
|
+
continue;
|
|
295
|
+
}
|
|
296
|
+
for (let j = events.length - 1; j > confirmationEventIndex; j--) {
|
|
297
|
+
const eventToCheck = events[j];
|
|
298
|
+
const functionResponses = getFunctionResponses(eventToCheck);
|
|
299
|
+
if (!functionResponses) {
|
|
300
|
+
continue;
|
|
301
|
+
}
|
|
302
|
+
for (const fr of functionResponses) {
|
|
303
|
+
if (fr.id && fr.id in toolsToResumeWithConfirmation) {
|
|
304
|
+
delete toolsToResumeWithConfirmation[fr.id];
|
|
305
|
+
delete toolsToResumeWithArgs[fr.id];
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
if (Object.keys(toolsToResumeWithConfirmation).length === 0) {
|
|
309
|
+
break;
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
if (Object.keys(toolsToResumeWithConfirmation).length === 0) {
|
|
313
|
+
continue;
|
|
314
|
+
}
|
|
315
|
+
const toolsList = await agent.canonicalTools(new ReadonlyContext(invocationContext));
|
|
316
|
+
const toolsDict = Object.fromEntries(toolsList.map((tool) => [tool.name, tool]));
|
|
317
|
+
const functionResponseEvent = await handleFunctionCallList({
|
|
318
|
+
invocationContext,
|
|
319
|
+
functionCalls: Object.values(toolsToResumeWithArgs),
|
|
320
|
+
toolsDict,
|
|
321
|
+
beforeToolCallbacks: agent.canonicalBeforeToolCallbacks,
|
|
322
|
+
afterToolCallbacks: agent.canonicalAfterToolCallbacks,
|
|
323
|
+
filters: new Set(Object.keys(toolsToResumeWithConfirmation)),
|
|
324
|
+
toolConfirmationDict: toolsToResumeWithConfirmation
|
|
325
|
+
});
|
|
326
|
+
if (functionResponseEvent) {
|
|
327
|
+
yield functionResponseEvent;
|
|
328
|
+
}
|
|
329
|
+
return;
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
const REQUEST_CONFIRMATION_LLM_REQUEST_PROCESSOR = new RequestConfirmationLlmRequestProcessor();
|
|
334
|
+
class CodeExecutionRequestProcessor extends BaseLlmRequestProcessor {
|
|
335
|
+
async *runAsync(invocationContext, llmRequest) {
|
|
336
|
+
if (!(invocationContext.agent instanceof LlmAgent)) {
|
|
337
|
+
return;
|
|
338
|
+
}
|
|
339
|
+
if (!invocationContext.agent.codeExecutor) {
|
|
340
|
+
return;
|
|
341
|
+
}
|
|
342
|
+
for await (const event of runPreProcessor(invocationContext, llmRequest)) {
|
|
343
|
+
yield event;
|
|
344
|
+
}
|
|
345
|
+
if (!(invocationContext.agent.codeExecutor instanceof BaseCodeExecutor)) {
|
|
346
|
+
return;
|
|
347
|
+
}
|
|
348
|
+
for (const content of llmRequest.contents) {
|
|
349
|
+
const delimeters = invocationContext.agent.codeExecutor.codeBlockDelimiters.length ? invocationContext.agent.codeExecutor.codeBlockDelimiters[0] : ["", ""];
|
|
350
|
+
const codeExecutionParts = convertCodeExecutionParts(
|
|
351
|
+
content,
|
|
352
|
+
delimeters,
|
|
353
|
+
invocationContext.agent.codeExecutor.executionResultDelimiters
|
|
354
|
+
);
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
const DATA_FILE_UTIL_MAP = {
|
|
359
|
+
"text/csv": {
|
|
360
|
+
extension: ".csv",
|
|
361
|
+
loaderCodeTemplate: "pd.read_csv('{filename}')"
|
|
362
|
+
}
|
|
363
|
+
};
|
|
364
|
+
const DATA_FILE_HELPER_LIB = `
|
|
365
|
+
import pandas as pd
|
|
366
|
+
|
|
367
|
+
def explore_df(df: pd.DataFrame) -> None:
|
|
368
|
+
"""Prints some information about a pandas DataFrame."""
|
|
369
|
+
|
|
370
|
+
with pd.option_context(
|
|
371
|
+
'display.max_columns', None, 'display.expand_frame_repr', False
|
|
372
|
+
):
|
|
373
|
+
# Print the column names to never encounter KeyError when selecting one.
|
|
374
|
+
df_dtypes = df.dtypes
|
|
375
|
+
|
|
376
|
+
# Obtain information about data types and missing values.
|
|
377
|
+
df_nulls = (len(df) - df.isnull().sum()).apply(
|
|
378
|
+
lambda x: f'{x} / {df.shape[0]} non-null'
|
|
379
|
+
)
|
|
380
|
+
|
|
381
|
+
# Explore unique total values in columns using \`.unique()\`.
|
|
382
|
+
df_unique_count = df.apply(lambda x: len(x.unique()))
|
|
383
|
+
|
|
384
|
+
# Explore unique values in columns using \`.unique()\`.
|
|
385
|
+
df_unique = df.apply(lambda x: crop(str(list(x.unique()))))
|
|
386
|
+
|
|
387
|
+
df_info = pd.concat(
|
|
388
|
+
(
|
|
389
|
+
df_dtypes.rename('Dtype'),
|
|
390
|
+
df_nulls.rename('Non-Null Count'),
|
|
391
|
+
df_unique_count.rename('Unique Values Count'),
|
|
392
|
+
df_unique.rename('Unique Values'),
|
|
393
|
+
),
|
|
394
|
+
axis=1,
|
|
395
|
+
)
|
|
396
|
+
df_info.index.name = 'Columns'
|
|
397
|
+
print(f"""Total rows: {df.shape[0]}
|
|
398
|
+
Total columns: {df.shape[1]}
|
|
399
|
+
|
|
400
|
+
{df_info}""")
|
|
401
|
+
`;
|
|
402
|
+
class CodeExecutionResponseProcessor {
|
|
403
|
+
/**
|
|
404
|
+
* Processes the LLM response asynchronously.
|
|
405
|
+
*
|
|
406
|
+
* @param invocationContext The invocation context
|
|
407
|
+
* @param llmResponse The LLM response to process
|
|
408
|
+
* @returns An async generator yielding events
|
|
409
|
+
*/
|
|
410
|
+
async *runAsync(invocationContext, llmResponse) {
|
|
411
|
+
if (llmResponse.partial) {
|
|
412
|
+
return;
|
|
413
|
+
}
|
|
414
|
+
for await (const event of runPostProcessor(invocationContext, llmResponse)) {
|
|
415
|
+
yield event;
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
const responseProcessor = new CodeExecutionResponseProcessor();
|
|
420
|
+
async function* runPreProcessor(invocationContext, llmRequest) {
|
|
421
|
+
const agent = invocationContext.agent;
|
|
422
|
+
if (!(agent instanceof LlmAgent)) {
|
|
423
|
+
return;
|
|
424
|
+
}
|
|
425
|
+
const codeExecutor = agent.codeExecutor;
|
|
426
|
+
if (!codeExecutor || !(codeExecutor instanceof BaseCodeExecutor)) {
|
|
427
|
+
return;
|
|
428
|
+
}
|
|
429
|
+
if (codeExecutor instanceof BuiltInCodeExecutor) {
|
|
430
|
+
codeExecutor.processLlmRequest(llmRequest);
|
|
431
|
+
return;
|
|
432
|
+
}
|
|
433
|
+
if (!codeExecutor.optimizeDataFile) {
|
|
434
|
+
return;
|
|
435
|
+
}
|
|
436
|
+
const codeExecutorContext = new CodeExecutorContext(new State(invocationContext.session.state));
|
|
437
|
+
if (codeExecutorContext.getErrorCount(invocationContext.invocationId) >= codeExecutor.errorRetryAttempts) {
|
|
438
|
+
return;
|
|
439
|
+
}
|
|
440
|
+
const allInputFiles = extractAndReplaceInlineFiles(codeExecutorContext, llmRequest);
|
|
441
|
+
const processedFileNames = new Set(codeExecutorContext.getProcessedFileNames());
|
|
442
|
+
const filesToProcess = allInputFiles.filter((f) => !processedFileNames.has(f.name));
|
|
443
|
+
for (const file of filesToProcess) {
|
|
444
|
+
const codeStr = getDataFilePreprocessingCode(file);
|
|
445
|
+
if (!codeStr) {
|
|
446
|
+
return;
|
|
447
|
+
}
|
|
448
|
+
const codeContent = {
|
|
449
|
+
role: "model",
|
|
450
|
+
parts: [
|
|
451
|
+
{ text: `Processing input file: \`${file.name}\`` },
|
|
452
|
+
buildExecutableCodePart(codeStr)
|
|
453
|
+
]
|
|
454
|
+
};
|
|
455
|
+
llmRequest.contents.push(deepClone(codeContent));
|
|
456
|
+
yield createEvent({
|
|
457
|
+
invocationId: invocationContext.invocationId,
|
|
458
|
+
author: agent.name,
|
|
459
|
+
branch: invocationContext.branch,
|
|
460
|
+
content: codeContent
|
|
461
|
+
});
|
|
462
|
+
const executionId = getOrSetExecutionId(invocationContext, codeExecutorContext);
|
|
463
|
+
const codeExecutionResult = await codeExecutor.executeCode({
|
|
464
|
+
invocationContext,
|
|
465
|
+
codeExecutionInput: {
|
|
466
|
+
code: codeStr,
|
|
467
|
+
inputFiles: [file],
|
|
468
|
+
executionId
|
|
469
|
+
}
|
|
470
|
+
});
|
|
471
|
+
codeExecutorContext.updateCodeExecutionResult({
|
|
472
|
+
invocationId: invocationContext.invocationId,
|
|
473
|
+
code: codeStr,
|
|
474
|
+
resultStdout: codeExecutionResult.stdout,
|
|
475
|
+
resultStderr: codeExecutionResult.stderr
|
|
476
|
+
});
|
|
477
|
+
codeExecutorContext.addProcessedFileNames([file.name]);
|
|
478
|
+
const executionResultEvent = await postProcessCodeExecutionResult(
|
|
479
|
+
invocationContext,
|
|
480
|
+
codeExecutorContext,
|
|
481
|
+
codeExecutionResult
|
|
482
|
+
);
|
|
483
|
+
yield executionResultEvent;
|
|
484
|
+
llmRequest.contents.push(deepClone(executionResultEvent.content));
|
|
485
|
+
}
|
|
486
|
+
}
|
|
487
|
+
async function* runPostProcessor(invocationContext, llmResponse) {
|
|
488
|
+
const agent = invocationContext.agent;
|
|
489
|
+
if (!(agent instanceof LlmAgent)) {
|
|
490
|
+
return;
|
|
491
|
+
}
|
|
492
|
+
const codeExecutor = agent.codeExecutor;
|
|
493
|
+
if (!codeExecutor || !(codeExecutor instanceof BaseCodeExecutor)) {
|
|
494
|
+
return;
|
|
495
|
+
}
|
|
496
|
+
if (!llmResponse || !llmResponse.content) {
|
|
497
|
+
return;
|
|
498
|
+
}
|
|
499
|
+
if (codeExecutor instanceof BuiltInCodeExecutor) {
|
|
500
|
+
return;
|
|
501
|
+
}
|
|
502
|
+
const codeExecutorContext = new CodeExecutorContext(new State(invocationContext.session.state));
|
|
503
|
+
if (codeExecutorContext.getErrorCount(invocationContext.invocationId) >= codeExecutor.errorRetryAttempts) {
|
|
504
|
+
return;
|
|
505
|
+
}
|
|
506
|
+
const responseContent = llmResponse.content;
|
|
507
|
+
const codeStr = extractCodeAndTruncateContent(
|
|
508
|
+
responseContent,
|
|
509
|
+
codeExecutor.codeBlockDelimiters
|
|
510
|
+
);
|
|
511
|
+
if (!codeStr) {
|
|
512
|
+
return;
|
|
513
|
+
}
|
|
514
|
+
yield createEvent({
|
|
515
|
+
invocationId: invocationContext.invocationId,
|
|
516
|
+
author: agent.name,
|
|
517
|
+
branch: invocationContext.branch,
|
|
518
|
+
content: responseContent
|
|
519
|
+
});
|
|
520
|
+
const executionId = getOrSetExecutionId(invocationContext, codeExecutorContext);
|
|
521
|
+
const codeExecutionResult = await codeExecutor.executeCode({
|
|
522
|
+
invocationContext,
|
|
523
|
+
codeExecutionInput: {
|
|
524
|
+
code: codeStr,
|
|
525
|
+
inputFiles: codeExecutorContext.getInputFiles(),
|
|
526
|
+
executionId
|
|
527
|
+
}
|
|
528
|
+
});
|
|
529
|
+
codeExecutorContext.updateCodeExecutionResult({
|
|
530
|
+
invocationId: invocationContext.invocationId,
|
|
531
|
+
code: codeStr,
|
|
532
|
+
resultStdout: codeExecutionResult.stdout,
|
|
533
|
+
resultStderr: codeExecutionResult.stderr
|
|
534
|
+
});
|
|
535
|
+
yield await postProcessCodeExecutionResult(
|
|
536
|
+
invocationContext,
|
|
537
|
+
codeExecutorContext,
|
|
538
|
+
codeExecutionResult
|
|
539
|
+
);
|
|
540
|
+
llmResponse.content = null;
|
|
541
|
+
}
|
|
542
|
+
function extractAndReplaceInlineFiles(codeExecutorContext, llmRequest) {
|
|
543
|
+
var _a;
|
|
544
|
+
const allInputFiles = codeExecutorContext.getInputFiles();
|
|
545
|
+
const savedFileNames = new Set(allInputFiles.map((f) => f.name));
|
|
546
|
+
for (let i = 0; i < llmRequest.contents.length; i++) {
|
|
547
|
+
const content = llmRequest.contents[i];
|
|
548
|
+
if (content.role !== "user" || !content.parts) {
|
|
549
|
+
continue;
|
|
550
|
+
}
|
|
551
|
+
for (let j = 0; j < content.parts.length; j++) {
|
|
552
|
+
const part = content.parts[j];
|
|
553
|
+
const mimeType = (_a = part.inlineData) == null ? void 0 : _a.mimeType;
|
|
554
|
+
if (!mimeType || !part.inlineData || !DATA_FILE_UTIL_MAP[mimeType]) {
|
|
555
|
+
continue;
|
|
556
|
+
}
|
|
557
|
+
const fileName = `data_${i + 1}_${j + 1}${DATA_FILE_UTIL_MAP[mimeType].extension}`;
|
|
558
|
+
part.text = `
|
|
559
|
+
Available file: \`${fileName}\`
|
|
560
|
+
`;
|
|
561
|
+
const file = {
|
|
562
|
+
name: fileName,
|
|
563
|
+
content: base64Decode(part.inlineData.data),
|
|
564
|
+
mimeType
|
|
565
|
+
};
|
|
566
|
+
if (!savedFileNames.has(fileName)) {
|
|
567
|
+
codeExecutorContext.addInputFiles([file]);
|
|
568
|
+
allInputFiles.push(file);
|
|
569
|
+
}
|
|
570
|
+
}
|
|
571
|
+
}
|
|
572
|
+
return allInputFiles;
|
|
573
|
+
}
|
|
574
|
+
function getOrSetExecutionId(invocationContext, codeExecutorContext) {
|
|
575
|
+
var _a;
|
|
576
|
+
const agent = invocationContext.agent;
|
|
577
|
+
if (!(agent instanceof LlmAgent) || !((_a = agent.codeExecutor) == null ? void 0 : _a.stateful)) {
|
|
578
|
+
return void 0;
|
|
579
|
+
}
|
|
580
|
+
let executionId = codeExecutorContext.getExecutionId();
|
|
581
|
+
if (!executionId) {
|
|
582
|
+
executionId = invocationContext.session.id;
|
|
583
|
+
codeExecutorContext.setExecutionId(executionId);
|
|
584
|
+
}
|
|
585
|
+
return executionId;
|
|
586
|
+
}
|
|
587
|
+
async function postProcessCodeExecutionResult(invocationContext, codeExecutorContext, codeExecutionResult) {
|
|
588
|
+
if (!invocationContext.artifactService) {
|
|
589
|
+
throw new Error("Artifact service is not initialized.");
|
|
590
|
+
}
|
|
591
|
+
const resultContent = {
|
|
592
|
+
role: "model",
|
|
593
|
+
parts: [buildCodeExecutionResultPart(codeExecutionResult)]
|
|
594
|
+
};
|
|
595
|
+
const eventActions = createEventActions({ stateDelta: codeExecutorContext.getStateDelta() });
|
|
596
|
+
if (codeExecutionResult.stderr) {
|
|
597
|
+
codeExecutorContext.incrementErrorCount(invocationContext.invocationId);
|
|
598
|
+
} else {
|
|
599
|
+
codeExecutorContext.resetErrorCount(invocationContext.invocationId);
|
|
600
|
+
}
|
|
601
|
+
for (const outputFile of codeExecutionResult.outputFiles) {
|
|
602
|
+
const version = await invocationContext.artifactService.saveArtifact({
|
|
603
|
+
appName: invocationContext.appName || "",
|
|
604
|
+
userId: invocationContext.userId || "",
|
|
605
|
+
sessionId: invocationContext.session.id,
|
|
606
|
+
filename: outputFile.name,
|
|
607
|
+
artifact: {
|
|
608
|
+
inlineData: { data: outputFile.content, mimeType: outputFile.mimeType }
|
|
609
|
+
}
|
|
610
|
+
});
|
|
611
|
+
eventActions.artifactDelta[outputFile.name] = version;
|
|
612
|
+
}
|
|
613
|
+
return createEvent({
|
|
614
|
+
invocationId: invocationContext.invocationId,
|
|
615
|
+
author: invocationContext.agent.name,
|
|
616
|
+
branch: invocationContext.branch,
|
|
617
|
+
content: resultContent,
|
|
618
|
+
actions: eventActions
|
|
619
|
+
});
|
|
620
|
+
}
|
|
621
|
+
function getDataFilePreprocessingCode(file) {
|
|
622
|
+
function getNormalizedFileName(fileName) {
|
|
623
|
+
const [varName2] = fileName.split(".");
|
|
624
|
+
let normalizedName = varName2.replace(/[^a-zA-Z0-9_]/g, "_");
|
|
625
|
+
if (/^\d/.test(normalizedName)) {
|
|
626
|
+
normalizedName = "_" + normalizedName;
|
|
627
|
+
}
|
|
628
|
+
return normalizedName;
|
|
629
|
+
}
|
|
630
|
+
if (!DATA_FILE_UTIL_MAP[file.mimeType]) {
|
|
631
|
+
return void 0;
|
|
632
|
+
}
|
|
633
|
+
const varName = getNormalizedFileName(file.name);
|
|
634
|
+
const loaderCode = DATA_FILE_UTIL_MAP[file.mimeType].loaderCodeTemplate.replace(
|
|
635
|
+
"{filename}",
|
|
636
|
+
file.name
|
|
637
|
+
);
|
|
638
|
+
return `
|
|
639
|
+
${DATA_FILE_HELPER_LIB}
|
|
640
|
+
|
|
641
|
+
# Load the dataframe.
|
|
642
|
+
${varName} = ${loaderCode}
|
|
643
|
+
|
|
644
|
+
# Use \`explore_df\` to guide my analysis.
|
|
645
|
+
explore_df(${varName})
|
|
646
|
+
`;
|
|
647
|
+
}
|
|
648
|
+
const CODE_EXECUTION_REQUEST_PROCESSOR = new CodeExecutionRequestProcessor();
|
|
649
|
+
const _LlmAgent = class _LlmAgent extends BaseAgent {
|
|
650
|
+
constructor(config) {
|
|
651
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _i;
|
|
652
|
+
super(config);
|
|
653
|
+
this.model = config.model;
|
|
654
|
+
this.instruction = (_a = config.instruction) != null ? _a : "";
|
|
655
|
+
this.globalInstruction = (_b = config.globalInstruction) != null ? _b : "";
|
|
656
|
+
this.tools = (_c = config.tools) != null ? _c : [];
|
|
657
|
+
this.generateContentConfig = config.generateContentConfig;
|
|
658
|
+
this.disallowTransferToParent = (_d = config.disallowTransferToParent) != null ? _d : false;
|
|
659
|
+
this.disallowTransferToPeers = (_e = config.disallowTransferToPeers) != null ? _e : false;
|
|
660
|
+
this.includeContents = (_f = config.includeContents) != null ? _f : "default";
|
|
661
|
+
this.inputSchema = config.inputSchema;
|
|
662
|
+
this.outputSchema = config.outputSchema;
|
|
663
|
+
this.outputKey = config.outputKey;
|
|
664
|
+
this.beforeModelCallback = config.beforeModelCallback;
|
|
665
|
+
this.afterModelCallback = config.afterModelCallback;
|
|
666
|
+
this.beforeToolCallback = config.beforeToolCallback;
|
|
667
|
+
this.afterToolCallback = config.afterToolCallback;
|
|
668
|
+
this.codeExecutor = config.codeExecutor;
|
|
669
|
+
this.requestProcessors = (_g = config.requestProcessors) != null ? _g : [
|
|
670
|
+
BASIC_LLM_REQUEST_PROCESSOR,
|
|
671
|
+
IDENTITY_LLM_REQUEST_PROCESSOR,
|
|
672
|
+
INSTRUCTIONS_LLM_REQUEST_PROCESSOR,
|
|
673
|
+
REQUEST_CONFIRMATION_LLM_REQUEST_PROCESSOR,
|
|
674
|
+
CONTENT_REQUEST_PROCESSOR,
|
|
675
|
+
CODE_EXECUTION_REQUEST_PROCESSOR
|
|
676
|
+
];
|
|
677
|
+
this.responseProcessors = (_h = config.responseProcessors) != null ? _h : [];
|
|
678
|
+
const agentTransferDisabled = this.disallowTransferToParent && this.disallowTransferToPeers && !((_i = this.subAgents) == null ? void 0 : _i.length);
|
|
679
|
+
if (!agentTransferDisabled) {
|
|
680
|
+
this.requestProcessors.push(AGENT_TRANSFER_LLM_REQUEST_PROCESSOR);
|
|
681
|
+
}
|
|
682
|
+
if (config.generateContentConfig) {
|
|
683
|
+
if (config.generateContentConfig.tools) {
|
|
684
|
+
throw new Error("All tools must be set via LlmAgent.tools.");
|
|
685
|
+
}
|
|
686
|
+
if (config.generateContentConfig.systemInstruction) {
|
|
687
|
+
throw new Error(
|
|
688
|
+
"System instruction must be set via LlmAgent.instruction."
|
|
689
|
+
);
|
|
690
|
+
}
|
|
691
|
+
if (config.generateContentConfig.responseSchema) {
|
|
692
|
+
throw new Error(
|
|
693
|
+
"Response schema must be set via LlmAgent.output_schema."
|
|
694
|
+
);
|
|
695
|
+
}
|
|
696
|
+
} else {
|
|
697
|
+
this.generateContentConfig = {};
|
|
698
|
+
}
|
|
699
|
+
if (this.outputSchema) {
|
|
700
|
+
if (!this.disallowTransferToParent || !this.disallowTransferToPeers) {
|
|
701
|
+
logger.warn(
|
|
702
|
+
`Invalid config for agent ${this.name}: outputSchema cannot co-exist with agent transfer configurations. Setting disallowTransferToParent=true, disallowTransferToPeers=true`
|
|
703
|
+
);
|
|
704
|
+
this.disallowTransferToParent = true;
|
|
705
|
+
this.disallowTransferToPeers = true;
|
|
706
|
+
}
|
|
707
|
+
if (this.subAgents && this.subAgents.length > 0) {
|
|
708
|
+
throw new Error(
|
|
709
|
+
`Invalid config for agent ${this.name}: if outputSchema is set, subAgents must be empty to disable agent transfer.`
|
|
710
|
+
);
|
|
711
|
+
}
|
|
712
|
+
if (this.tools && this.tools.length > 0) {
|
|
713
|
+
throw new Error(
|
|
714
|
+
`Invalid config for agent ${this.name}: if outputSchema is set, tools must be empty`
|
|
715
|
+
);
|
|
716
|
+
}
|
|
717
|
+
}
|
|
718
|
+
}
|
|
719
|
+
/**
|
|
720
|
+
* The resolved BaseLlm instance.
|
|
721
|
+
*
|
|
722
|
+
* When not set, the agent will inherit the model from its ancestor.
|
|
723
|
+
*/
|
|
724
|
+
get canonicalModel() {
|
|
725
|
+
if (isBaseLlm(this.model)) {
|
|
726
|
+
return this.model;
|
|
727
|
+
}
|
|
728
|
+
if (typeof this.model === "string" && this.model) {
|
|
729
|
+
return LLMRegistry.newLlm(this.model);
|
|
730
|
+
}
|
|
731
|
+
let ancestorAgent = this.parentAgent;
|
|
732
|
+
while (ancestorAgent) {
|
|
733
|
+
if (ancestorAgent instanceof _LlmAgent) {
|
|
734
|
+
return ancestorAgent.canonicalModel;
|
|
735
|
+
}
|
|
736
|
+
ancestorAgent = ancestorAgent.parentAgent;
|
|
737
|
+
}
|
|
738
|
+
throw new Error(`No model found for ${this.name}.`);
|
|
739
|
+
}
|
|
740
|
+
/**
|
|
741
|
+
* The resolved self.instruction field to construct instruction for this
|
|
742
|
+
* agent.
|
|
743
|
+
*
|
|
744
|
+
* This method is only for use by Agent Development Kit.
|
|
745
|
+
* @param context The context to retrieve the session state.
|
|
746
|
+
* @returns The resolved self.instruction field.
|
|
747
|
+
*/
|
|
748
|
+
async canonicalInstruction(context) {
|
|
749
|
+
if (typeof this.instruction === "string") {
|
|
750
|
+
return { instruction: this.instruction, requireStateInjection: true };
|
|
751
|
+
}
|
|
752
|
+
return {
|
|
753
|
+
instruction: await this.instruction(context),
|
|
754
|
+
requireStateInjection: false
|
|
755
|
+
};
|
|
756
|
+
}
|
|
757
|
+
/**
|
|
758
|
+
* The resolved self.instruction field to construct global instruction.
|
|
759
|
+
*
|
|
760
|
+
* This method is only for use by Agent Development Kit.
|
|
761
|
+
* @param context The context to retrieve the session state.
|
|
762
|
+
* @returns The resolved self.global_instruction field.
|
|
763
|
+
*/
|
|
764
|
+
async canonicalGlobalInstruction(context) {
|
|
765
|
+
if (typeof this.globalInstruction === "string") {
|
|
766
|
+
return { instruction: this.globalInstruction, requireStateInjection: true };
|
|
767
|
+
}
|
|
768
|
+
return {
|
|
769
|
+
instruction: await this.globalInstruction(context),
|
|
770
|
+
requireStateInjection: false
|
|
771
|
+
};
|
|
772
|
+
}
|
|
773
|
+
/**
|
|
774
|
+
* The resolved self.tools field as a list of BaseTool based on the context.
|
|
775
|
+
*
|
|
776
|
+
* This method is only for use by Agent Development Kit.
|
|
777
|
+
*/
|
|
778
|
+
async canonicalTools(context) {
|
|
779
|
+
const resolvedTools = [];
|
|
780
|
+
for (const toolUnion of this.tools) {
|
|
781
|
+
const tools = await convertToolUnionToTools(toolUnion, context);
|
|
782
|
+
resolvedTools.push(...tools);
|
|
783
|
+
}
|
|
784
|
+
return resolvedTools;
|
|
785
|
+
}
|
|
786
|
+
/**
|
|
787
|
+
* Normalizes a callback or an array of callbacks into an array of callbacks.
|
|
788
|
+
*
|
|
789
|
+
* @param callback The callback or an array of callbacks.
|
|
790
|
+
* @returns An array of callbacks.
|
|
791
|
+
*/
|
|
792
|
+
static normalizeCallbackArray(callback) {
|
|
793
|
+
if (!callback) {
|
|
794
|
+
return [];
|
|
795
|
+
}
|
|
796
|
+
if (Array.isArray(callback)) {
|
|
797
|
+
return callback;
|
|
798
|
+
}
|
|
799
|
+
return [callback];
|
|
800
|
+
}
|
|
801
|
+
/**
|
|
802
|
+
* The resolved self.before_model_callback field as a list of
|
|
803
|
+
* SingleBeforeModelCallback.
|
|
804
|
+
*
|
|
805
|
+
* This method is only for use by Agent Development Kit.
|
|
806
|
+
*/
|
|
807
|
+
get canonicalBeforeModelCallbacks() {
|
|
808
|
+
return _LlmAgent.normalizeCallbackArray(this.beforeModelCallback);
|
|
809
|
+
}
|
|
810
|
+
/**
|
|
811
|
+
* The resolved self.after_model_callback field as a list of
|
|
812
|
+
* SingleAfterModelCallback.
|
|
813
|
+
*
|
|
814
|
+
* This method is only for use by Agent Development Kit.
|
|
815
|
+
*/
|
|
816
|
+
get canonicalAfterModelCallbacks() {
|
|
817
|
+
return _LlmAgent.normalizeCallbackArray(this.afterModelCallback);
|
|
818
|
+
}
|
|
819
|
+
/**
|
|
820
|
+
* The resolved self.before_tool_callback field as a list of
|
|
821
|
+
* BeforeToolCallback.
|
|
822
|
+
*
|
|
823
|
+
* This method is only for use by Agent Development Kit.
|
|
824
|
+
*/
|
|
825
|
+
get canonicalBeforeToolCallbacks() {
|
|
826
|
+
return _LlmAgent.normalizeCallbackArray(this.beforeToolCallback);
|
|
827
|
+
}
|
|
828
|
+
/**
|
|
829
|
+
* The resolved self.after_tool_callback field as a list of AfterToolCallback.
|
|
830
|
+
*
|
|
831
|
+
* This method is only for use by Agent Development Kit.
|
|
832
|
+
*/
|
|
833
|
+
get canonicalAfterToolCallbacks() {
|
|
834
|
+
return _LlmAgent.normalizeCallbackArray(this.afterToolCallback);
|
|
835
|
+
}
|
|
836
|
+
/**
|
|
837
|
+
* Saves the agent's final response to the session state if configured.
|
|
838
|
+
*
|
|
839
|
+
* It extracts the text content from the final response event, optionally
|
|
840
|
+
* parses it as JSON based on the output schema, and stores the result in the
|
|
841
|
+
* session state using the specified output key.
|
|
842
|
+
*
|
|
843
|
+
* @param event The event to process.
|
|
844
|
+
*/
|
|
845
|
+
maybeSaveOutputToState(event) {
|
|
846
|
+
var _a, _b;
|
|
847
|
+
if (event.author !== this.name) {
|
|
848
|
+
logger.debug(
|
|
849
|
+
`Skipping output save for agent ${this.name}: event authored by ${event.author}`
|
|
850
|
+
);
|
|
851
|
+
return;
|
|
852
|
+
}
|
|
853
|
+
if (!this.outputKey) {
|
|
854
|
+
logger.debug(
|
|
855
|
+
`Skipping output save for agent ${this.name}: outputKey is not set`
|
|
856
|
+
);
|
|
857
|
+
return;
|
|
858
|
+
}
|
|
859
|
+
if (!isFinalResponse(event)) {
|
|
860
|
+
logger.debug(
|
|
861
|
+
`Skipping output save for agent ${this.name}: event is not a final response`
|
|
862
|
+
);
|
|
863
|
+
return;
|
|
864
|
+
}
|
|
865
|
+
if (!((_b = (_a = event.content) == null ? void 0 : _a.parts) == null ? void 0 : _b.length)) {
|
|
866
|
+
logger.debug(
|
|
867
|
+
`Skipping output save for agent ${this.name}: event content is empty`
|
|
868
|
+
);
|
|
869
|
+
return;
|
|
870
|
+
}
|
|
871
|
+
const resultStr = event.content.parts.map((part) => part.text ? part.text : "").join("");
|
|
872
|
+
let result = resultStr;
|
|
873
|
+
if (this.outputSchema) {
|
|
874
|
+
if (!resultStr.trim()) {
|
|
875
|
+
return;
|
|
876
|
+
}
|
|
877
|
+
try {
|
|
878
|
+
result = JSON.parse(resultStr);
|
|
879
|
+
} catch (e) {
|
|
880
|
+
logger.error(`Error parsing output for agent ${this.name}`, e);
|
|
881
|
+
}
|
|
882
|
+
}
|
|
883
|
+
event.actions.stateDelta[this.outputKey] = result;
|
|
884
|
+
}
|
|
885
|
+
async *runAsyncImpl(context) {
|
|
886
|
+
while (true) {
|
|
887
|
+
let lastEvent = void 0;
|
|
888
|
+
for await (const event of this.runOneStepAsync(context)) {
|
|
889
|
+
lastEvent = event;
|
|
890
|
+
this.maybeSaveOutputToState(event);
|
|
891
|
+
yield event;
|
|
892
|
+
}
|
|
893
|
+
if (!lastEvent || isFinalResponse(lastEvent)) {
|
|
894
|
+
break;
|
|
895
|
+
}
|
|
896
|
+
if (lastEvent.partial) {
|
|
897
|
+
logger.warn("The last event is partial, which is not expected.");
|
|
898
|
+
break;
|
|
899
|
+
}
|
|
900
|
+
}
|
|
901
|
+
}
|
|
902
|
+
async *runLiveImpl(context) {
|
|
903
|
+
for await (const event of this.runLiveFlow(context)) {
|
|
904
|
+
this.maybeSaveOutputToState(event);
|
|
905
|
+
yield event;
|
|
906
|
+
}
|
|
907
|
+
if (context.endInvocation) {
|
|
908
|
+
return;
|
|
909
|
+
}
|
|
910
|
+
}
|
|
911
|
+
// --------------------------------------------------------------------------
|
|
912
|
+
// #START LlmFlow Logic
|
|
913
|
+
// --------------------------------------------------------------------------
|
|
914
|
+
async *runLiveFlow(invocationContext) {
|
|
915
|
+
await Promise.resolve();
|
|
916
|
+
throw new Error("LlmAgent.runLiveFlow not implemented");
|
|
917
|
+
}
|
|
918
|
+
async *runOneStepAsync(invocationContext) {
|
|
919
|
+
const llmRequest = {
|
|
920
|
+
contents: [],
|
|
921
|
+
toolsDict: {},
|
|
922
|
+
liveConnectConfig: {}
|
|
923
|
+
};
|
|
924
|
+
for (const processor of this.requestProcessors) {
|
|
925
|
+
for await (const event of processor.runAsync(invocationContext, llmRequest)) {
|
|
926
|
+
yield event;
|
|
927
|
+
}
|
|
928
|
+
}
|
|
929
|
+
for (const toolUnion of this.tools) {
|
|
930
|
+
const toolContext = new ToolContext({ invocationContext });
|
|
931
|
+
const tools = await convertToolUnionToTools(
|
|
932
|
+
toolUnion,
|
|
933
|
+
new ReadonlyContext(invocationContext)
|
|
934
|
+
);
|
|
935
|
+
for (const tool of tools) {
|
|
936
|
+
await tool.processLlmRequest({ toolContext, llmRequest });
|
|
937
|
+
}
|
|
938
|
+
}
|
|
939
|
+
if (invocationContext.endInvocation) {
|
|
940
|
+
return;
|
|
941
|
+
}
|
|
942
|
+
const modelResponseEvent = createEvent({
|
|
943
|
+
invocationId: invocationContext.invocationId,
|
|
944
|
+
author: this.name,
|
|
945
|
+
branch: invocationContext.branch
|
|
946
|
+
});
|
|
947
|
+
for await (const llmResponse of this.callLlmAsync(
|
|
948
|
+
invocationContext,
|
|
949
|
+
llmRequest,
|
|
950
|
+
modelResponseEvent
|
|
951
|
+
)) {
|
|
952
|
+
try {
|
|
953
|
+
for await (const event of this.postprocess(
|
|
954
|
+
invocationContext,
|
|
955
|
+
llmRequest,
|
|
956
|
+
llmResponse,
|
|
957
|
+
modelResponseEvent
|
|
958
|
+
)) {
|
|
959
|
+
modelResponseEvent.id = createNewEventId();
|
|
960
|
+
modelResponseEvent.timestamp = (/* @__PURE__ */ new Date()).getTime();
|
|
961
|
+
yield event;
|
|
962
|
+
}
|
|
963
|
+
} catch (postprocessError) {
|
|
964
|
+
const errMsg = postprocessError instanceof Error ? postprocessError.message : String(postprocessError);
|
|
965
|
+
logger.error(`Postprocess error: ${errMsg}`);
|
|
966
|
+
yield createEvent({
|
|
967
|
+
invocationId: invocationContext.invocationId,
|
|
968
|
+
author: this.name,
|
|
969
|
+
branch: invocationContext.branch,
|
|
970
|
+
errorCode: "POSTPROCESS_ERROR",
|
|
971
|
+
errorMessage: errMsg
|
|
972
|
+
});
|
|
973
|
+
}
|
|
974
|
+
}
|
|
975
|
+
}
|
|
976
|
+
async *postprocess(invocationContext, llmRequest, llmResponse, modelResponseEvent) {
|
|
977
|
+
var _a, _b;
|
|
978
|
+
for (const processor of this.responseProcessors) {
|
|
979
|
+
for await (const event of processor.runAsync(invocationContext, llmResponse)) {
|
|
980
|
+
yield event;
|
|
981
|
+
}
|
|
982
|
+
}
|
|
983
|
+
if (!llmResponse.content && !llmResponse.errorCode && !llmResponse.interrupted) {
|
|
984
|
+
return;
|
|
985
|
+
}
|
|
986
|
+
const mergedEvent = createEvent({
|
|
987
|
+
...modelResponseEvent,
|
|
988
|
+
...llmResponse
|
|
989
|
+
});
|
|
990
|
+
if (mergedEvent.content) {
|
|
991
|
+
const functionCalls = getFunctionCalls(mergedEvent);
|
|
992
|
+
if (functionCalls == null ? void 0 : functionCalls.length) {
|
|
993
|
+
populateClientFunctionCallId(mergedEvent);
|
|
994
|
+
mergedEvent.longRunningToolIds = Array.from(
|
|
995
|
+
getLongRunningFunctionCalls(functionCalls, llmRequest.toolsDict)
|
|
996
|
+
);
|
|
997
|
+
const hasSignature = (_a = mergedEvent.content.parts) == null ? void 0 : _a.some(
|
|
998
|
+
(p) => p.thoughtSignature
|
|
999
|
+
);
|
|
1000
|
+
if (!hasSignature) {
|
|
1001
|
+
logger.warn(
|
|
1002
|
+
`[postprocess] Function calls (${functionCalls.length}) without thoughtSignature`
|
|
1003
|
+
);
|
|
1004
|
+
}
|
|
1005
|
+
}
|
|
1006
|
+
}
|
|
1007
|
+
yield mergedEvent;
|
|
1008
|
+
if (!((_b = getFunctionCalls(mergedEvent)) == null ? void 0 : _b.length)) {
|
|
1009
|
+
return;
|
|
1010
|
+
}
|
|
1011
|
+
const functionResponseEvent = await handleFunctionCallsAsync({
|
|
1012
|
+
invocationContext,
|
|
1013
|
+
functionCallEvent: mergedEvent,
|
|
1014
|
+
toolsDict: llmRequest.toolsDict,
|
|
1015
|
+
beforeToolCallbacks: this.canonicalBeforeToolCallbacks,
|
|
1016
|
+
afterToolCallbacks: this.canonicalAfterToolCallbacks
|
|
1017
|
+
});
|
|
1018
|
+
if (!functionResponseEvent) {
|
|
1019
|
+
return;
|
|
1020
|
+
}
|
|
1021
|
+
const authEvent = generateAuthEvent(invocationContext, functionResponseEvent);
|
|
1022
|
+
if (authEvent) {
|
|
1023
|
+
yield authEvent;
|
|
1024
|
+
}
|
|
1025
|
+
const toolConfirmationEvent = generateRequestConfirmationEvent({
|
|
1026
|
+
invocationContext,
|
|
1027
|
+
functionCallEvent: mergedEvent,
|
|
1028
|
+
functionResponseEvent
|
|
1029
|
+
});
|
|
1030
|
+
if (toolConfirmationEvent) {
|
|
1031
|
+
yield toolConfirmationEvent;
|
|
1032
|
+
}
|
|
1033
|
+
yield functionResponseEvent;
|
|
1034
|
+
const nextAgentName = functionResponseEvent.actions.transferToAgent;
|
|
1035
|
+
if (nextAgentName) {
|
|
1036
|
+
const nextAgent = this.getAgentByName(invocationContext, nextAgentName);
|
|
1037
|
+
for await (const event of nextAgent.runAsync(invocationContext)) {
|
|
1038
|
+
yield event;
|
|
1039
|
+
}
|
|
1040
|
+
}
|
|
1041
|
+
}
|
|
1042
|
+
/**
|
|
1043
|
+
* Retrieves an agent from the agent tree by its name.
|
|
1044
|
+
*
|
|
1045
|
+
* Performing a depth-first search to locate the agent with the given name.
|
|
1046
|
+
* - Starts searching from the root agent of the current invocation context.
|
|
1047
|
+
* - Traverses down the agent tree to find the specified agent.
|
|
1048
|
+
*
|
|
1049
|
+
* @param invocationContext The current invocation context.
|
|
1050
|
+
* @param agentName The name of the agent to retrieve.
|
|
1051
|
+
* @returns The agent with the given name.
|
|
1052
|
+
* @throws Error if the agent is not found.
|
|
1053
|
+
*/
|
|
1054
|
+
getAgentByName(invocationContext, agentName) {
|
|
1055
|
+
const rootAgent = invocationContext.agent.rootAgent;
|
|
1056
|
+
const agentToRun = rootAgent.findAgent(agentName);
|
|
1057
|
+
if (!agentToRun) {
|
|
1058
|
+
throw new Error(`Agent ${agentName} not found in the agent tree.`);
|
|
1059
|
+
}
|
|
1060
|
+
return agentToRun;
|
|
1061
|
+
}
|
|
1062
|
+
async *callLlmAsync(invocationContext, llmRequest, modelResponseEvent) {
|
|
1063
|
+
var _a, _b, _c, _d, _e;
|
|
1064
|
+
const beforeModelResponse = await this.handleBeforeModelCallback(
|
|
1065
|
+
invocationContext,
|
|
1066
|
+
llmRequest,
|
|
1067
|
+
modelResponseEvent
|
|
1068
|
+
);
|
|
1069
|
+
if (beforeModelResponse) {
|
|
1070
|
+
yield beforeModelResponse;
|
|
1071
|
+
return;
|
|
1072
|
+
}
|
|
1073
|
+
(_a = llmRequest.config) != null ? _a : llmRequest.config = {};
|
|
1074
|
+
(_c = (_b = llmRequest.config).labels) != null ? _c : _b.labels = {};
|
|
1075
|
+
if (!llmRequest.config.labels[ADK_AGENT_NAME_LABEL_KEY]) {
|
|
1076
|
+
llmRequest.config.labels[ADK_AGENT_NAME_LABEL_KEY] = this.name;
|
|
1077
|
+
}
|
|
1078
|
+
const llm = this.canonicalModel;
|
|
1079
|
+
if ((_d = invocationContext.runConfig) == null ? void 0 : _d.supportCfc) {
|
|
1080
|
+
throw new Error("CFC is not yet supported in callLlmAsync");
|
|
1081
|
+
} else {
|
|
1082
|
+
invocationContext.incrementLlmCallCount();
|
|
1083
|
+
const isStreaming = ((_e = invocationContext.runConfig) == null ? void 0 : _e.streamingMode) === StreamingMode.SSE;
|
|
1084
|
+
const maxRetries = _LlmAgent.LLM_TRANSIENT_ERROR_MAX_RETRIES;
|
|
1085
|
+
for (let attempt = 0; attempt <= maxRetries; attempt++) {
|
|
1086
|
+
if (attempt > 0) {
|
|
1087
|
+
const delay = Math.min(
|
|
1088
|
+
_LlmAgent.LLM_TRANSIENT_ERROR_BASE_DELAY_MS * Math.pow(2, attempt - 1),
|
|
1089
|
+
_LlmAgent.LLM_TRANSIENT_ERROR_MAX_DELAY_MS
|
|
1090
|
+
);
|
|
1091
|
+
logger.warn(
|
|
1092
|
+
`[callLlmAsync] Retrying LLM call after transient error (attempt ${attempt + 1}/${maxRetries + 1}), waiting ${delay}ms`
|
|
1093
|
+
);
|
|
1094
|
+
await new Promise((resolve) => setTimeout(resolve, delay));
|
|
1095
|
+
}
|
|
1096
|
+
const responsesGenerator = llm.generateContentAsync(
|
|
1097
|
+
llmRequest,
|
|
1098
|
+
isStreaming
|
|
1099
|
+
);
|
|
1100
|
+
let shouldRetry = false;
|
|
1101
|
+
let contentYielded = false;
|
|
1102
|
+
for await (const llmResponse of this.runAndHandleError(
|
|
1103
|
+
responsesGenerator,
|
|
1104
|
+
invocationContext,
|
|
1105
|
+
llmRequest,
|
|
1106
|
+
modelResponseEvent
|
|
1107
|
+
)) {
|
|
1108
|
+
if (llmResponse.content) {
|
|
1109
|
+
contentYielded = true;
|
|
1110
|
+
}
|
|
1111
|
+
if (llmResponse.errorCode && _LlmAgent.LLM_RETRYABLE_ERROR_CODES.has(llmResponse.errorCode) && !contentYielded && attempt < maxRetries) {
|
|
1112
|
+
shouldRetry = true;
|
|
1113
|
+
logger.warn(
|
|
1114
|
+
`[callLlmAsync] Transient LLM error: ${llmResponse.errorCode}, usage: ${JSON.stringify(llmResponse.usageMetadata)}`
|
|
1115
|
+
);
|
|
1116
|
+
break;
|
|
1117
|
+
}
|
|
1118
|
+
const alteredLlmResponse = await this.handleAfterModelCallback(
|
|
1119
|
+
invocationContext,
|
|
1120
|
+
llmResponse,
|
|
1121
|
+
modelResponseEvent
|
|
1122
|
+
);
|
|
1123
|
+
yield alteredLlmResponse != null ? alteredLlmResponse : llmResponse;
|
|
1124
|
+
}
|
|
1125
|
+
if (!shouldRetry) {
|
|
1126
|
+
return;
|
|
1127
|
+
}
|
|
1128
|
+
}
|
|
1129
|
+
}
|
|
1130
|
+
}
|
|
1131
|
+
async handleBeforeModelCallback(invocationContext, llmRequest, modelResponseEvent) {
|
|
1132
|
+
const callbackContext = new CallbackContext(
|
|
1133
|
+
{ invocationContext, eventActions: modelResponseEvent.actions }
|
|
1134
|
+
);
|
|
1135
|
+
const beforeModelCallbackResponse = await invocationContext.pluginManager.runBeforeModelCallback(
|
|
1136
|
+
{ callbackContext, llmRequest }
|
|
1137
|
+
);
|
|
1138
|
+
if (beforeModelCallbackResponse) {
|
|
1139
|
+
return beforeModelCallbackResponse;
|
|
1140
|
+
}
|
|
1141
|
+
for (const callback of this.canonicalBeforeModelCallbacks) {
|
|
1142
|
+
const callbackResponse = await callback({ context: callbackContext, request: llmRequest });
|
|
1143
|
+
if (callbackResponse) {
|
|
1144
|
+
return callbackResponse;
|
|
1145
|
+
}
|
|
1146
|
+
}
|
|
1147
|
+
return void 0;
|
|
1148
|
+
}
|
|
1149
|
+
async handleAfterModelCallback(invocationContext, llmResponse, modelResponseEvent) {
|
|
1150
|
+
const callbackContext = new CallbackContext(
|
|
1151
|
+
{ invocationContext, eventActions: modelResponseEvent.actions }
|
|
1152
|
+
);
|
|
1153
|
+
const afterModelCallbackResponse = await invocationContext.pluginManager.runAfterModelCallback(
|
|
1154
|
+
{ callbackContext, llmResponse }
|
|
1155
|
+
);
|
|
1156
|
+
if (afterModelCallbackResponse) {
|
|
1157
|
+
return afterModelCallbackResponse;
|
|
1158
|
+
}
|
|
1159
|
+
for (const callback of this.canonicalAfterModelCallbacks) {
|
|
1160
|
+
const callbackResponse = await callback({ context: callbackContext, response: llmResponse });
|
|
1161
|
+
if (callbackResponse) {
|
|
1162
|
+
return callbackResponse;
|
|
1163
|
+
}
|
|
1164
|
+
}
|
|
1165
|
+
return void 0;
|
|
1166
|
+
}
|
|
1167
|
+
async *runAndHandleError(responseGenerator, invocationContext, llmRequest, modelResponseEvent) {
|
|
1168
|
+
try {
|
|
1169
|
+
for await (const response of responseGenerator) {
|
|
1170
|
+
yield response;
|
|
1171
|
+
}
|
|
1172
|
+
} catch (modelError) {
|
|
1173
|
+
const callbackContext = new CallbackContext(
|
|
1174
|
+
{ invocationContext, eventActions: modelResponseEvent.actions }
|
|
1175
|
+
);
|
|
1176
|
+
if (modelError instanceof Error) {
|
|
1177
|
+
const onModelErrorCallbackResponse = await invocationContext.pluginManager.runOnModelErrorCallback({
|
|
1178
|
+
callbackContext,
|
|
1179
|
+
llmRequest,
|
|
1180
|
+
error: modelError
|
|
1181
|
+
});
|
|
1182
|
+
if (onModelErrorCallbackResponse) {
|
|
1183
|
+
yield onModelErrorCallbackResponse;
|
|
1184
|
+
} else {
|
|
1185
|
+
try {
|
|
1186
|
+
const errorResponse = JSON.parse(modelError.message);
|
|
1187
|
+
yield {
|
|
1188
|
+
errorCode: String(errorResponse.error.code),
|
|
1189
|
+
errorMessage: errorResponse.error.message
|
|
1190
|
+
};
|
|
1191
|
+
} catch {
|
|
1192
|
+
logger.warn(
|
|
1193
|
+
`LLM error message is not valid JSON, using raw message: ${modelError.message.substring(0, 200)}`
|
|
1194
|
+
);
|
|
1195
|
+
yield {
|
|
1196
|
+
errorCode: "UNKNOWN_ERROR",
|
|
1197
|
+
errorMessage: modelError.message
|
|
1198
|
+
};
|
|
1199
|
+
}
|
|
1200
|
+
}
|
|
1201
|
+
} else {
|
|
1202
|
+
logger.error("Unknown error during response generation", modelError);
|
|
1203
|
+
throw modelError;
|
|
1204
|
+
}
|
|
1205
|
+
}
|
|
1206
|
+
}
|
|
1207
|
+
// --------------------------------------------------------------------------
|
|
1208
|
+
// #END LlmFlow Logic
|
|
1209
|
+
// --------------------------------------------------------------------------
|
|
1210
|
+
// TODO - b/425992518: omitted Py LlmAgent features.
|
|
1211
|
+
// - code_executor
|
|
1212
|
+
// - configurable agents by yaml config
|
|
1213
|
+
};
|
|
1214
|
+
_LlmAgent.LLM_TRANSIENT_ERROR_MAX_RETRIES = 2;
|
|
1215
|
+
_LlmAgent.LLM_TRANSIENT_ERROR_BASE_DELAY_MS = 1e3;
|
|
1216
|
+
_LlmAgent.LLM_TRANSIENT_ERROR_MAX_DELAY_MS = 4e3;
|
|
1217
|
+
_LlmAgent.LLM_RETRYABLE_ERROR_CODES = /* @__PURE__ */ new Set([
|
|
1218
|
+
"UNKNOWN_ERROR"
|
|
1219
|
+
]);
|
|
1220
|
+
let LlmAgent = _LlmAgent;
|
|
1221
|
+
export {
|
|
1222
|
+
LlmAgent,
|
|
1223
|
+
REQUEST_CONFIRMATION_LLM_REQUEST_PROCESSOR,
|
|
1224
|
+
responseProcessor
|
|
1225
|
+
};
|