@google/adk 1.2.0 → 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (190) hide show
  1. package/dist/cjs/agents/base_agent.js +19 -1
  2. package/dist/cjs/agents/instructions.js +81 -33
  3. package/dist/cjs/agents/invocation_context.js +0 -1
  4. package/dist/cjs/agents/llm_agent.js +52 -5
  5. package/dist/cjs/agents/processors/agent_transfer_llm_request_processor.js +7 -0
  6. package/dist/cjs/agents/processors/basic_llm_request_processor.js +8 -1
  7. package/dist/cjs/agents/processors/content_processor_utils.js +37 -24
  8. package/dist/cjs/agents/processors/content_request_processor.js +7 -0
  9. package/dist/cjs/agents/processors/context_compactor_request_processor.js +12 -0
  10. package/dist/cjs/agents/processors/identity_llm_request_processor.js +7 -0
  11. package/dist/cjs/agents/processors/instructions_llm_request_processor.js +5 -0
  12. package/dist/cjs/agents/processors/request_confirmation_llm_request_processor.js +9 -1
  13. package/dist/cjs/agents/processors/tool_filter_request_processor.js +7 -1
  14. package/dist/cjs/auth/auth_preprocessor.js +12 -10
  15. package/dist/cjs/auth/oauth2/oauth2_discovery.js +1 -1
  16. package/dist/cjs/code_executors/code_executor_context.js +7 -7
  17. package/dist/cjs/common.js +39 -0
  18. package/dist/cjs/context/summarizers/llm_summarizer.js +11 -0
  19. package/dist/cjs/context/token_based_context_compactor.js +1 -1
  20. package/dist/cjs/events/event.js +1 -1
  21. package/dist/cjs/integrations/agent_registry/agent_registry_mcp_toolset.js +21 -2
  22. package/dist/cjs/models/gemini_llm_connection.js +62 -19
  23. package/dist/cjs/models/google_llm.js +26 -8
  24. package/dist/cjs/plugins/security_plugin.js +16 -0
  25. package/dist/cjs/sessions/base_session_service.js +13 -2
  26. package/dist/cjs/sessions/database_session_service.js +2 -2
  27. package/dist/cjs/sessions/db/schema.js +45 -10
  28. package/dist/cjs/sessions/in_memory_session_service.js +2 -1
  29. package/dist/cjs/sessions/vertex_ai_session_service.js +2 -1
  30. package/dist/cjs/skills/gcp_skill_registry.js +104 -0
  31. package/dist/cjs/skills/loader.js +65 -0
  32. package/dist/cjs/skills/skill_registry.js +27 -0
  33. package/dist/cjs/tools/openapi_tool/openapi_spec_parser/openapi_spec_parser.js +232 -0
  34. package/dist/cjs/tools/openapi_tool/openapi_spec_parser/operation_parser.js +224 -0
  35. package/dist/cjs/tools/openapi_tool/openapi_spec_parser/tool_auth_handler.js +127 -0
  36. package/dist/cjs/tools/openapi_tool/openapi_toolset.js +133 -0
  37. package/dist/cjs/tools/openapi_tool/rest_api_tool.js +256 -0
  38. package/dist/cjs/tools/skill/load_skill_resource_tool.js +25 -3
  39. package/dist/cjs/tools/skill/load_skill_tool.js +12 -1
  40. package/dist/cjs/tools/skill/run_skill_script_tool.js +12 -1
  41. package/dist/cjs/tools/skill/search_skills_tool.js +108 -0
  42. package/dist/cjs/tools/skill/skill_toolset.js +40 -5
  43. package/dist/cjs/utils/async_queue.js +88 -0
  44. package/dist/cjs/utils/case_utils.js +53 -0
  45. package/dist/cjs/utils/env_aware_utils.js +4 -0
  46. package/dist/cjs/utils/live_connection_utils.js +284 -0
  47. package/dist/cjs/utils/model_name.js +9 -0
  48. package/dist/cjs/utils/streaming_utils.js +9 -8
  49. package/dist/cjs/version.js +1 -1
  50. package/dist/esm/agents/base_agent.js +19 -1
  51. package/dist/esm/agents/instructions.js +81 -33
  52. package/dist/esm/agents/invocation_context.js +0 -1
  53. package/dist/esm/agents/llm_agent.js +53 -5
  54. package/dist/esm/agents/processors/agent_transfer_llm_request_processor.js +7 -0
  55. package/dist/esm/agents/processors/basic_llm_request_processor.js +8 -1
  56. package/dist/esm/agents/processors/content_processor_utils.js +35 -23
  57. package/dist/esm/agents/processors/content_request_processor.js +7 -0
  58. package/dist/esm/agents/processors/context_compactor_request_processor.js +12 -0
  59. package/dist/esm/agents/processors/identity_llm_request_processor.js +7 -0
  60. package/dist/esm/agents/processors/instructions_llm_request_processor.js +5 -0
  61. package/dist/esm/agents/processors/request_confirmation_llm_request_processor.js +9 -1
  62. package/dist/esm/agents/processors/tool_filter_request_processor.js +7 -1
  63. package/dist/esm/auth/auth_preprocessor.js +12 -10
  64. package/dist/esm/auth/oauth2/oauth2_discovery.js +1 -1
  65. package/dist/esm/code_executors/code_executor_context.js +7 -7
  66. package/dist/esm/common.js +33 -1
  67. package/dist/esm/context/summarizers/llm_summarizer.js +11 -0
  68. package/dist/esm/context/token_based_context_compactor.js +1 -1
  69. package/dist/esm/events/event.js +1 -1
  70. package/dist/esm/integrations/agent_registry/agent_registry_mcp_toolset.js +21 -2
  71. package/dist/esm/models/gemini_llm_connection.js +62 -19
  72. package/dist/esm/models/google_llm.js +26 -8
  73. package/dist/esm/plugins/security_plugin.js +16 -0
  74. package/dist/esm/sessions/base_session_service.js +11 -1
  75. package/dist/esm/sessions/database_session_service.js +2 -2
  76. package/dist/esm/sessions/db/schema.js +44 -10
  77. package/dist/esm/sessions/in_memory_session_service.js +4 -2
  78. package/dist/esm/sessions/vertex_ai_session_service.js +4 -2
  79. package/dist/esm/skills/gcp_skill_registry.js +78 -0
  80. package/dist/esm/skills/loader.js +64 -0
  81. package/dist/esm/skills/skill_registry.js +7 -0
  82. package/dist/esm/tools/openapi_tool/openapi_spec_parser/openapi_spec_parser.js +206 -0
  83. package/dist/esm/tools/openapi_tool/openapi_spec_parser/operation_parser.js +198 -0
  84. package/dist/esm/tools/openapi_tool/openapi_spec_parser/tool_auth_handler.js +101 -0
  85. package/dist/esm/tools/openapi_tool/openapi_toolset.js +97 -0
  86. package/dist/esm/tools/openapi_tool/rest_api_tool.js +229 -0
  87. package/dist/esm/tools/skill/load_skill_resource_tool.js +25 -3
  88. package/dist/esm/tools/skill/load_skill_tool.js +12 -1
  89. package/dist/esm/tools/skill/run_skill_script_tool.js +12 -1
  90. package/dist/esm/tools/skill/search_skills_tool.js +82 -0
  91. package/dist/esm/tools/skill/skill_toolset.js +40 -5
  92. package/dist/esm/utils/async_queue.js +60 -0
  93. package/dist/esm/utils/case_utils.js +25 -0
  94. package/dist/esm/utils/env_aware_utils.js +4 -0
  95. package/dist/esm/utils/live_connection_utils.js +256 -0
  96. package/dist/esm/utils/model_name.js +8 -0
  97. package/dist/esm/utils/streaming_utils.js +9 -8
  98. package/dist/esm/version.js +1 -1
  99. package/dist/types/a2a/a2a_remote_agent_utils.d.ts +29 -4
  100. package/dist/types/a2a/event_converter_utils.d.ts +14 -1
  101. package/dist/types/a2a/metadata_converter_utils.d.ts +18 -0
  102. package/dist/types/a2a/part_converter_utils.d.ts +51 -6
  103. package/dist/types/agents/invocation_context.d.ts +0 -9
  104. package/dist/types/agents/llm_agent.d.ts +14 -0
  105. package/dist/types/agents/processors/agent_transfer_llm_request_processor.d.ts +14 -0
  106. package/dist/types/agents/processors/basic_llm_request_processor.d.ts +7 -0
  107. package/dist/types/agents/processors/content_processor_utils.d.ts +26 -0
  108. package/dist/types/agents/processors/content_request_processor.d.ts +16 -0
  109. package/dist/types/agents/processors/context_compactor_request_processor.d.ts +12 -0
  110. package/dist/types/agents/processors/identity_llm_request_processor.d.ts +7 -0
  111. package/dist/types/agents/processors/request_confirmation_llm_request_processor.d.ts +9 -1
  112. package/dist/types/agents/processors/tool_filter_request_processor.d.ts +12 -1
  113. package/dist/types/common.d.ts +15 -1
  114. package/dist/types/context/summarizers/llm_summarizer.d.ts +17 -0
  115. package/dist/types/events/event_actions.d.ts +1 -2
  116. package/dist/types/integrations/agent_registry/agent_registry_mcp_toolset.d.ts +21 -2
  117. package/dist/types/models/base_llm_connection.d.ts +10 -0
  118. package/dist/types/models/gemini_llm_connection.d.ts +15 -4
  119. package/dist/types/models/llm_response.d.ts +10 -1
  120. package/dist/types/plugins/security_plugin.d.ts +30 -0
  121. package/dist/types/sessions/base_session_service.d.ts +4 -0
  122. package/dist/types/sessions/db/schema.d.ts +1 -0
  123. package/dist/types/skills/gcp_skill_registry.d.ts +24 -0
  124. package/dist/types/skills/loader.d.ts +7 -0
  125. package/dist/types/skills/skill.d.ts +1 -1
  126. package/dist/types/skills/skill_registry.d.ts +29 -0
  127. package/dist/types/tools/openapi_tool/openapi_spec_parser/openapi_spec_parser.d.ts +34 -0
  128. package/dist/types/tools/openapi_tool/openapi_spec_parser/operation_parser.d.ts +59 -0
  129. package/dist/types/tools/openapi_tool/openapi_spec_parser/tool_auth_handler.d.ts +23 -0
  130. package/dist/types/tools/openapi_tool/openapi_toolset.d.ts +27 -0
  131. package/dist/types/tools/openapi_tool/rest_api_tool.d.ts +50 -0
  132. package/dist/types/tools/skill/load_skill_resource_tool.d.ts +1 -1
  133. package/dist/types/tools/skill/search_skills_tool.d.ts +14 -0
  134. package/dist/types/tools/skill/skill_toolset.d.ts +5 -0
  135. package/dist/types/utils/async_queue.d.ts +18 -0
  136. package/dist/types/utils/case_utils.d.ts +12 -0
  137. package/dist/types/utils/live_connection_utils.d.ts +30 -0
  138. package/dist/types/utils/model_name.d.ts +7 -0
  139. package/dist/types/utils/streaming_utils.d.ts +0 -1
  140. package/dist/types/version.d.ts +1 -1
  141. package/dist/web/agents/base_agent.js +31 -1
  142. package/dist/web/agents/instructions.js +81 -33
  143. package/dist/web/agents/invocation_context.js +0 -1
  144. package/dist/web/agents/llm_agent.js +53 -5
  145. package/dist/web/agents/processors/agent_transfer_llm_request_processor.js +7 -0
  146. package/dist/web/agents/processors/basic_llm_request_processor.js +8 -1
  147. package/dist/web/agents/processors/content_processor_utils.js +53 -23
  148. package/dist/web/agents/processors/content_request_processor.js +7 -0
  149. package/dist/web/agents/processors/context_compactor_request_processor.js +12 -0
  150. package/dist/web/agents/processors/identity_llm_request_processor.js +7 -0
  151. package/dist/web/agents/processors/instructions_llm_request_processor.js +5 -0
  152. package/dist/web/agents/processors/request_confirmation_llm_request_processor.js +9 -1
  153. package/dist/web/agents/processors/tool_filter_request_processor.js +7 -1
  154. package/dist/web/auth/auth_preprocessor.js +12 -10
  155. package/dist/web/auth/oauth2/oauth2_discovery.js +1 -1
  156. package/dist/web/code_executors/code_executor_context.js +7 -7
  157. package/dist/web/common.js +33 -1
  158. package/dist/web/context/summarizers/llm_summarizer.js +11 -0
  159. package/dist/web/context/token_based_context_compactor.js +1 -1
  160. package/dist/web/events/event.js +1 -1
  161. package/dist/web/integrations/agent_registry/agent_registry_mcp_toolset.js +21 -2
  162. package/dist/web/models/gemini_llm_connection.js +75 -19
  163. package/dist/web/models/google_llm.js +26 -8
  164. package/dist/web/plugins/security_plugin.js +16 -0
  165. package/dist/web/sessions/base_session_service.js +11 -1
  166. package/dist/web/sessions/database_session_service.js +2 -2
  167. package/dist/web/sessions/db/schema.js +44 -10
  168. package/dist/web/sessions/in_memory_session_service.js +4 -2
  169. package/dist/web/sessions/vertex_ai_session_service.js +4 -2
  170. package/dist/web/skills/gcp_skill_registry.js +78 -0
  171. package/dist/web/skills/loader.js +64 -0
  172. package/dist/web/skills/skill_registry.js +7 -0
  173. package/dist/web/tools/openapi_tool/openapi_spec_parser/openapi_spec_parser.js +221 -0
  174. package/dist/web/tools/openapi_tool/openapi_spec_parser/operation_parser.js +198 -0
  175. package/dist/web/tools/openapi_tool/openapi_spec_parser/tool_auth_handler.js +101 -0
  176. package/dist/web/tools/openapi_tool/openapi_toolset.js +97 -0
  177. package/dist/web/tools/openapi_tool/rest_api_tool.js +229 -0
  178. package/dist/web/tools/skill/load_skill_resource_tool.js +25 -3
  179. package/dist/web/tools/skill/load_skill_tool.js +12 -1
  180. package/dist/web/tools/skill/run_skill_script_tool.js +12 -1
  181. package/dist/web/tools/skill/search_skills_tool.js +82 -0
  182. package/dist/web/tools/skill/skill_toolset.js +40 -5
  183. package/dist/web/utils/async_queue.js +60 -0
  184. package/dist/web/utils/case_utils.js +25 -0
  185. package/dist/web/utils/env_aware_utils.js +4 -0
  186. package/dist/web/utils/live_connection_utils.js +254 -0
  187. package/dist/web/utils/model_name.js +8 -0
  188. package/dist/web/utils/streaming_utils.js +9 -8
  189. package/dist/web/version.js +1 -1
  190. package/package.json +3 -1
@@ -124,9 +124,27 @@ class BaseAgent {
124
124
  ctx,
125
125
  this,
126
126
  async function* () {
127
+ var _a2, _b;
128
+ const context2 = this.createInvocationContext(parentContext);
129
+ const beforeAgentCallbackEvent = await this.handleBeforeAgentCallback(context2);
130
+ if (beforeAgentCallbackEvent) {
131
+ yield beforeAgentCallbackEvent;
132
+ }
133
+ if (context2.endInvocation || ((_a2 = parentContext.abortSignal) == null ? void 0 : _a2.aborted)) {
134
+ return;
135
+ }
136
+ for await (const event of this.runLiveImpl(context2)) {
137
+ yield event;
138
+ }
139
+ if (context2.endInvocation || ((_b = parentContext.abortSignal) == null ? void 0 : _b.aborted)) {
140
+ return;
141
+ }
142
+ const afterAgentCallbackEvent = await this.handleAfterAgentCallback(context2);
143
+ if (afterAgentCallbackEvent) {
144
+ yield afterAgentCallbackEvent;
145
+ }
127
146
  }
128
147
  );
129
- throw new Error("Live mode is not implemented yet.");
130
148
  } finally {
131
149
  span.end();
132
150
  }
@@ -33,50 +33,98 @@ var import_state = require("../sessions/state.js");
33
33
  * Copyright 2025 Google LLC
34
34
  * SPDX-License-Identifier: Apache-2.0
35
35
  */
36
- async function injectSessionState(template, readonlyContext) {
36
+ const ARTIFACT_PREFIX = "artifact.";
37
+ async function resolveKey(key, isOptional, rawMatch, readonlyContext) {
37
38
  const invocationContext = readonlyContext.invocationContext;
38
- async function replaceMatchedKeyWithItsValue(match) {
39
- let key = match[0].replace(/^\{+/, "").replace(/\}+$/, "").trim();
39
+ if (key.startsWith(ARTIFACT_PREFIX)) {
40
+ const fileName = key.substring(ARTIFACT_PREFIX.length);
41
+ if (invocationContext.artifactService === void 0) {
42
+ throw new Error("Artifact service is not initialized.");
43
+ }
44
+ const artifact = await invocationContext.artifactService.loadArtifact({
45
+ appName: invocationContext.session.appName,
46
+ userId: invocationContext.session.userId,
47
+ sessionId: invocationContext.session.id,
48
+ filename: fileName
49
+ });
50
+ if (!artifact) {
51
+ if (isOptional) {
52
+ return "";
53
+ }
54
+ throw new Error(`Artifact ${fileName} not found.`);
55
+ }
56
+ return String(artifact);
57
+ }
58
+ if (!isValidStateName(key)) {
59
+ return rawMatch;
60
+ }
61
+ if (key in invocationContext.session.state) {
62
+ return String(invocationContext.session.state[key]);
63
+ }
64
+ if (isOptional) {
65
+ return "";
66
+ }
67
+ throw new Error(`Context variable not found: \`${key}\`.`);
68
+ }
69
+ async function injectSessionState(template, readonlyContext) {
70
+ const pattern = /\{+[^{}]*}+/g;
71
+ const matches = Array.from(template.matchAll(pattern));
72
+ if (matches.length === 0) {
73
+ return template;
74
+ }
75
+ const parsedMatches = matches.map((match) => {
76
+ const raw = match[0];
77
+ let key = raw.replace(/^\{+/, "").replace(/\}+$/, "").trim();
40
78
  const isOptional = key.endsWith("?");
41
79
  if (isOptional) {
42
80
  key = key.slice(0, -1);
43
81
  }
44
- if (key.startsWith("artifact.")) {
45
- const fileName = key.substring("artifact.".length);
46
- if (invocationContext.artifactService === void 0) {
47
- throw new Error("Artifact service is not initialized.");
82
+ const isValid = key.startsWith(ARTIFACT_PREFIX) || isValidStateName(key);
83
+ return {
84
+ raw,
85
+ key,
86
+ isOptional,
87
+ isValid,
88
+ index: match.index
89
+ };
90
+ });
91
+ const uniqueKeys = /* @__PURE__ */ new Map();
92
+ for (const pm of parsedMatches) {
93
+ if (!pm.isValid) {
94
+ continue;
95
+ }
96
+ const existing = uniqueKeys.get(pm.key);
97
+ if (existing) {
98
+ if (existing.isOptional && !pm.isOptional) {
99
+ existing.isOptional = false;
48
100
  }
49
- const artifact = await invocationContext.artifactService.loadArtifact({
50
- appName: invocationContext.session.appName,
51
- userId: invocationContext.session.userId,
52
- sessionId: invocationContext.session.id,
53
- filename: fileName
101
+ } else {
102
+ uniqueKeys.set(pm.key, {
103
+ key: pm.key,
104
+ isOptional: pm.isOptional,
105
+ raw: pm.raw
54
106
  });
55
- if (!artifact) {
56
- throw new Error(`Artifact ${fileName} not found.`);
57
- }
58
- return String(artifact);
59
- }
60
- if (!isValidStateName(key)) {
61
- return match[0];
62
- }
63
- if (key in invocationContext.session.state) {
64
- return String(invocationContext.session.state[key]);
65
107
  }
66
- if (isOptional) {
67
- return "";
68
- }
69
- throw new Error(`Context variable not found: \`${key}\`.`);
70
108
  }
71
- const pattern = /\{+[^{}]*}+/g;
109
+ const resolutions = /* @__PURE__ */ new Map();
110
+ for (const info of uniqueKeys.values()) {
111
+ resolutions.set(
112
+ info.key,
113
+ resolveKey(info.key, info.isOptional, info.raw, readonlyContext)
114
+ );
115
+ }
116
+ await Promise.all(resolutions.values());
72
117
  const result = [];
73
118
  let lastEnd = 0;
74
- const matches = template.matchAll(pattern);
75
- for (const match of matches) {
76
- result.push(template.slice(lastEnd, match.index));
77
- const replacement = await replaceMatchedKeyWithItsValue(match);
78
- result.push(replacement);
79
- lastEnd = match.index + match[0].length;
119
+ for (const pm of parsedMatches) {
120
+ result.push(template.slice(lastEnd, pm.index));
121
+ if (pm.isValid) {
122
+ const replacement = await resolutions.get(pm.key);
123
+ result.push(replacement);
124
+ } else {
125
+ result.push(pm.raw);
126
+ }
127
+ lastEnd = pm.index + pm.raw.length;
80
128
  }
81
129
  result.push(template.slice(lastEnd));
82
130
  return result.join("");
@@ -74,7 +74,6 @@ class InvocationContext {
74
74
  this.endInvocation = params.endInvocation || false;
75
75
  this.transcriptionCache = params.transcriptionCache;
76
76
  this.runConfig = params.runConfig;
77
- this.liveRequestQueue = params.liveRequestQueue;
78
77
  this.activeStreamingTools = params.activeStreamingTools;
79
78
  this.pluginManager = params.pluginManager;
80
79
  this.abortSignal = params.abortSignal;
@@ -29,6 +29,7 @@ __export(llm_agent_exports, {
29
29
  });
30
30
  module.exports = __toCommonJS(llm_agent_exports);
31
31
  var import_api = require("@opentelemetry/api");
32
+ var import_function_tool = require("../tools/function_tool.js");
32
33
  var import_event = require("../events/event.js");
33
34
  var import_base_llm = require("../models/base_llm.js");
34
35
  var import_registry = require("../models/registry.js");
@@ -39,6 +40,7 @@ var import_tracing = require("../telemetry/tracing.js");
39
40
  var import_simple_zod_to_json = require("../utils/simple_zod_to_json.js");
40
41
  var import_base_agent = require("./base_agent.js");
41
42
  var import_functions = require("./functions.js");
43
+ var import_auth_preprocessor = require("../auth/auth_preprocessor.js");
42
44
  var import_agent_transfer_llm_request_processor = require("./processors/agent_transfer_llm_request_processor.js");
43
45
  var import_basic_llm_request_processor = require("./processors/basic_llm_request_processor.js");
44
46
  var import_code_execution_request_processor = require("./processors/code_execution_request_processor.js");
@@ -91,6 +93,7 @@ class LlmAgent extends (_b = import_base_agent.BaseAgent, _a = LLM_AGENT_SIGNATU
91
93
  this.codeExecutor = config.codeExecutor;
92
94
  this.requestProcessors = (_g = config.requestProcessors) != null ? _g : [
93
95
  import_basic_llm_request_processor.BASIC_LLM_REQUEST_PROCESSOR,
96
+ import_auth_preprocessor.AUTH_PREPROCESSOR,
94
97
  import_identity_llm_request_processor.IDENTITY_LLM_REQUEST_PROCESSOR,
95
98
  import_instructions_llm_request_processor.INSTRUCTIONS_LLM_REQUEST_PROCESSOR,
96
99
  import_request_confirmation_llm_request_processor.REQUEST_CONFIRMATION_LLM_REQUEST_PROCESSOR,
@@ -316,18 +319,26 @@ class LlmAgent extends (_b = import_base_agent.BaseAgent, _a = LLM_AGENT_SIGNATU
316
319
  event.actions.stateDelta[this.outputKey] = result;
317
320
  }
318
321
  async *runAsyncImpl(context2) {
319
- var _a2;
322
+ var _a2, _b2;
320
323
  while (true) {
321
324
  let lastEvent = void 0;
325
+ let stepHadToolCalls = false;
322
326
  for await (const event of this.runOneStepAsync(context2)) {
323
327
  if ((_a2 = context2.abortSignal) == null ? void 0 : _a2.aborted) {
324
328
  return;
325
329
  }
326
330
  lastEvent = event;
331
+ if ((0, import_event.getFunctionCalls)(event).length > 0 || (0, import_event.getFunctionResponses)(event).length > 0) {
332
+ stepHadToolCalls = true;
333
+ }
327
334
  this.maybeSaveOutputToState(event);
328
335
  yield event;
329
336
  }
330
- if (!lastEvent || (0, import_event.isFinalResponse)(lastEvent)) {
337
+ if (!lastEvent) {
338
+ break;
339
+ }
340
+ const isEmptyMetadataEvent = lastEvent.author === this.name && !lastEvent.partial && (!((_b2 = lastEvent.content) == null ? void 0 : _b2.parts) || lastEvent.content.parts.length === 0);
341
+ if ((0, import_event.isFinalResponse)(lastEvent) && !(isEmptyMetadataEvent && stepHadToolCalls)) {
331
342
  break;
332
343
  }
333
344
  if (lastEvent.partial) {
@@ -352,6 +363,20 @@ class LlmAgent extends (_b = import_base_agent.BaseAgent, _a = LLM_AGENT_SIGNATU
352
363
  // --------------------------------------------------------------------------
353
364
  // #START LlmFlow Logic
354
365
  // --------------------------------------------------------------------------
366
+ /**
367
+ * Runs the bidirectional (live) flow for this agent.
368
+ *
369
+ * Establishes a live connection to the model, drains the invocation's
370
+ * `liveRequestQueue` into the connection on a parallel task, and yields
371
+ * events derived from server messages until the queue closes, the model
372
+ * finishes, or an agent transfer occurs.
373
+ *
374
+ * If the live connection drops (network failure, server `goAway`) and a
375
+ * session resumption handle has been observed, the flow transparently
376
+ * reconnects using that handle up to {@link MAX_LIVE_RECONNECT_ATTEMPTS}
377
+ * times. Subsequent reconnects skip `sendHistory` because the server
378
+ * already holds the conversation state associated with the handle.
379
+ */
355
380
  // eslint-disable-next-line require-yield
356
381
  async *runLiveFlow(_invocationContext) {
357
382
  await Promise.resolve();
@@ -375,13 +400,28 @@ class LlmAgent extends (_b = import_base_agent.BaseAgent, _a = LLM_AGENT_SIGNATU
375
400
  yield event;
376
401
  }
377
402
  }
378
- for (const toolUnion of this.tools) {
403
+ const allTools = [...this.tools];
404
+ if (this.outputSchema && allTools.length > 0) {
405
+ const setModelResponseTool = new import_function_tool.FunctionTool({
406
+ name: "set_model_response",
407
+ description: "Call this tool to submit your final response conforming to the output schema. Use this tool only when you have collected all the information and are ready to return the final answer.",
408
+ parameters: this.outputSchema,
409
+ execute: async (args, toolContext) => {
410
+ if (toolContext) {
411
+ toolContext.actions.skipSummarization = true;
412
+ }
413
+ return JSON.stringify(args);
414
+ }
415
+ });
416
+ allTools.push(setModelResponseTool);
417
+ }
418
+ for (const toolUnion of allTools) {
379
419
  const toolContext = new import_context.Context({ invocationContext });
380
420
  const tools = (await convertToolUnionToTools(
381
421
  toolUnion,
382
422
  new import_readonly_context.ReadonlyContext(invocationContext)
383
423
  )).filter((tool) => {
384
- return !llmRequest.allowedTools || llmRequest.allowedTools.includes(tool.name);
424
+ return !llmRequest.allowedTools || llmRequest.allowedTools.includes(tool.name) || tool.name === "set_model_response";
385
425
  });
386
426
  for (const tool of tools) {
387
427
  await tool.processLlmRequest({ toolContext, llmRequest });
@@ -461,7 +501,14 @@ class LlmAgent extends (_b = import_base_agent.BaseAgent, _a = LLM_AGENT_SIGNATU
461
501
  });
462
502
  if (mergedEvent.content) {
463
503
  const functionCalls = (0, import_event.getFunctionCalls)(mergedEvent);
464
- if (functionCalls == null ? void 0 : functionCalls.length) {
504
+ const setModelResponseCall = functionCalls.find(
505
+ (call) => call.name === "set_model_response"
506
+ );
507
+ if (setModelResponseCall) {
508
+ const args = setModelResponseCall.args;
509
+ mergedEvent.content.parts = [{ text: JSON.stringify(args) }];
510
+ mergedEvent.actions.skipSummarization = true;
511
+ } else if (functionCalls && functionCalls.length) {
465
512
  (0, import_functions.populateClientFunctionCallId)(mergedEvent);
466
513
  mergedEvent.longRunningToolIds = Array.from(
467
514
  (0, import_functions.getLongRunningFunctionCalls)(functionCalls, llmRequest.toolsDict)
@@ -58,6 +58,13 @@ class AgentTransferLlmRequestProcessor extends import_base_llm_processor.BaseLlm
58
58
  }
59
59
  });
60
60
  }
61
+ /**
62
+ * Appends transfer instructions and registers the `transfer_to_agent` tool
63
+ * when the agent has reachable transfer targets.
64
+ *
65
+ * @param invocationContext - The current invocation context.
66
+ * @param llmRequest - The request to augment with transfer instructions and the transfer tool.
67
+ */
61
68
  // eslint-disable-next-line require-yield
62
69
  async *runAsync(invocationContext, llmRequest) {
63
70
  if (!(0, import_llm_agent.isLlmAgent)(invocationContext.agent)) {
@@ -37,6 +37,13 @@ var import_base_llm_processor = require("./base_llm_processor.js");
37
37
  * SPDX-License-Identifier: Apache-2.0
38
38
  */
39
39
  class BasicLlmRequestProcessor extends import_base_llm_processor.BaseLlmRequestProcessor {
40
+ /**
41
+ * Populates model name, generation config, output schema, and live connect
42
+ * settings on the request from the agent and run config.
43
+ *
44
+ * @param invocationContext - The current invocation context.
45
+ * @param llmRequest - The request object to populate in place.
46
+ */
40
47
  // eslint-disable-next-line require-yield
41
48
  async *runAsync(invocationContext, llmRequest) {
42
49
  var _a;
@@ -46,7 +53,7 @@ class BasicLlmRequestProcessor extends import_base_llm_processor.BaseLlmRequestP
46
53
  }
47
54
  llmRequest.model = agent.canonicalModel.model;
48
55
  llmRequest.config = { ...(_a = agent.generateContentConfig) != null ? _a : {} };
49
- if (agent.outputSchema) {
56
+ if (agent.outputSchema && (!agent.tools || agent.tools.length === 0)) {
50
57
  (0, import_llm_request.setOutputSchema)(llmRequest, agent.outputSchema);
51
58
  }
52
59
  if (invocationContext.runConfig) {
@@ -25,7 +25,8 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
25
25
  var content_processor_utils_exports = {};
26
26
  __export(content_processor_utils_exports, {
27
27
  getContents: () => getContents,
28
- getCurrentTurnContents: () => getCurrentTurnContents
28
+ getCurrentTurnContents: () => getCurrentTurnContents,
29
+ mergeFunctionResponseEvents: () => mergeFunctionResponseEvents
29
30
  });
30
31
  module.exports = __toCommonJS(content_processor_utils_exports);
31
32
  var import_genai = require("@google/genai");
@@ -127,17 +128,19 @@ function convertForeignEvent(event) {
127
128
  text: `[${event.author}] said: ${part.text}`
128
129
  });
129
130
  } else if (part.functionCall) {
130
- const argsText = safeStringify(part.functionCall.args);
131
131
  (_d = content.parts) == null ? void 0 : _d.push({
132
- text: `[${event.author}] called tool \`${part.functionCall.name}\` with parameters: ${argsText}`
132
+ text: `[${event.author}] called tool \`${part.functionCall.name}\` with parameters: ${safeStringify(
133
+ part.functionCall.args
134
+ )}`
133
135
  });
134
136
  } else if (part.functionResponse) {
135
- const responseText = safeStringify(part.functionResponse.response);
136
137
  (_e = content.parts) == null ? void 0 : _e.push({
137
- text: `[${event.author}] tool \`${part.functionResponse.name}\` returned result: ${responseText}`
138
+ text: `[${event.author}] tool \`${part.functionResponse.name}\` returned result: ${safeStringify(
139
+ part.functionResponse.response
140
+ )}`
138
141
  });
139
142
  } else {
140
- (_f = content.parts) == null ? void 0 : _f.push(part);
143
+ (_f = content.parts) == null ? void 0 : _f.push((0, import_lodash_es.cloneDeep)(part));
141
144
  }
142
145
  }
143
146
  return (0, import_event.createEvent)({
@@ -153,9 +156,12 @@ function mergeFunctionResponseEvents(events) {
153
156
  if (events.length === 0) {
154
157
  throw new Error("Cannot merge an empty list of events.");
155
158
  }
156
- const mergedEvent = (0, import_event.createEvent)(events[0]);
157
- const partsInMergedEvent = ((_a = mergedEvent.content) == null ? void 0 : _a.parts) || [];
158
- if (partsInMergedEvent.length === 0) {
159
+ const mergedEvent = (0, import_event.createEvent)({
160
+ ...events[0],
161
+ content: events[0].content ? (0, import_lodash_es.cloneDeep)(events[0].content) : void 0
162
+ });
163
+ const partsInMergedEvent = (_a = mergedEvent.content) == null ? void 0 : _a.parts;
164
+ if (!partsInMergedEvent || partsInMergedEvent.length === 0) {
159
165
  throw new Error("There should be at least one function_response part.");
160
166
  }
161
167
  const partIndicesInMergedEvent = {};
@@ -170,16 +176,17 @@ function mergeFunctionResponseEvents(events) {
170
176
  throw new Error("There should be at least one function_response part.");
171
177
  }
172
178
  for (const part of event.content.parts) {
173
- if (part.functionResponse && part.functionResponse.id) {
174
- const functionCallId = part.functionResponse.id;
179
+ const clonedPart = (0, import_lodash_es.cloneDeep)(part);
180
+ if (clonedPart.functionResponse && clonedPart.functionResponse.id) {
181
+ const functionCallId = clonedPart.functionResponse.id;
175
182
  if (functionCallId in partIndicesInMergedEvent) {
176
- partsInMergedEvent[partIndicesInMergedEvent[functionCallId]] = part;
183
+ partsInMergedEvent[partIndicesInMergedEvent[functionCallId]] = clonedPart;
177
184
  } else {
178
- partsInMergedEvent.push(part);
185
+ partsInMergedEvent.push(clonedPart);
179
186
  partIndicesInMergedEvent[functionCallId] = partsInMergedEvent.length - 1;
180
187
  }
181
188
  } else {
182
- partsInMergedEvent.push(part);
189
+ partsInMergedEvent.push(clonedPart);
183
190
  }
184
191
  }
185
192
  }
@@ -194,7 +201,7 @@ function rearrangeEventsForLatestFunctionResponse(events) {
194
201
  if (!(functionResponses == null ? void 0 : functionResponses.length)) {
195
202
  return events;
196
203
  }
197
- let functionResponsesIds = new Set(
204
+ const functionResponsesIds = new Set(
198
205
  functionResponses.filter((response) => !!response.id).map((response) => response.id)
199
206
  );
200
207
  const secondLatestEvent = events.at(-2);
@@ -208,16 +215,16 @@ function rearrangeEventsForLatestFunctionResponse(events) {
208
215
  }
209
216
  }
210
217
  }
211
- let functionCallEventIdx = -1;
218
+ let match;
212
219
  for (let idx = events.length - 2; idx >= 0; idx--) {
213
220
  const event = events[idx];
214
221
  const functionCalls = (0, import_event.getFunctionCalls)(event);
215
222
  if (!(functionCalls == null ? void 0 : functionCalls.length)) {
216
223
  continue;
217
224
  }
225
+ let matchedInEvent = false;
218
226
  for (const functionCall of functionCalls) {
219
227
  if (functionCall.id && functionResponsesIds.has(functionCall.id)) {
220
- functionCallEventIdx = idx;
221
228
  const functionCallIds = new Set(
222
229
  functionCalls.map((fc) => fc.id).filter((id) => !!id)
223
230
  );
@@ -231,12 +238,16 @@ function rearrangeEventsForLatestFunctionResponse(events) {
231
238
  )}, function response ids provided: ${Array.from(functionResponsesIds).join(", ")}`
232
239
  );
233
240
  }
234
- functionResponsesIds = functionCallIds;
241
+ match = { eventIdx: idx, responseIds: functionCallIds };
242
+ matchedInEvent = true;
235
243
  break;
236
244
  }
237
245
  }
246
+ if (matchedInEvent) {
247
+ break;
248
+ }
238
249
  }
239
- if (functionCallEventIdx === -1) {
250
+ if (!match) {
240
251
  throw new Error(
241
252
  `No function call event found for function responses ids: ${Array.from(
242
253
  functionResponsesIds
@@ -244,17 +255,18 @@ function rearrangeEventsForLatestFunctionResponse(events) {
244
255
  );
245
256
  }
246
257
  const functionResponseEvents = [];
247
- for (let idx = functionCallEventIdx + 1; idx < events.length - 1; idx++) {
258
+ const activeResponses = match.responseIds;
259
+ for (let idx = match.eventIdx + 1; idx < events.length - 1; idx++) {
248
260
  const event = events[idx];
249
261
  const responses = (0, import_event.getFunctionResponses)(event);
250
262
  if (responses && responses.some(
251
- (response) => response.id && functionResponsesIds.has(response.id)
263
+ (response) => response.id && activeResponses.has(response.id)
252
264
  )) {
253
265
  functionResponseEvents.push(event);
254
266
  }
255
267
  }
256
268
  functionResponseEvents.push(events[events.length - 1]);
257
- const resultEvents = events.slice(0, functionCallEventIdx + 1);
269
+ const resultEvents = events.slice(0, match.eventIdx + 1);
258
270
  resultEvents.push(mergeFunctionResponseEvents(functionResponseEvents));
259
271
  return resultEvents;
260
272
  }
@@ -293,7 +305,7 @@ function rearrangeEventsForAsyncFunctionResponsesInHistory(events) {
293
305
  continue;
294
306
  }
295
307
  if (functionResponseEventsIndices.size === 1) {
296
- const [responseIndex] = [...functionResponseEventsIndices];
308
+ const [responseIndex] = Array.from(functionResponseEventsIndices);
297
309
  resultEvents.push(events[responseIndex]);
298
310
  } else {
299
311
  const indicesArray = Array.from(functionResponseEventsIndices).sort(
@@ -334,5 +346,6 @@ ${event.compactedContent}`
334
346
  // Annotate the CommonJS export names for ESM import in node:
335
347
  0 && (module.exports = {
336
348
  getContents,
337
- getCurrentTurnContents
349
+ getCurrentTurnContents,
350
+ mergeFunctionResponseEvents
338
351
  });
@@ -37,6 +37,13 @@ var import_content_processor_utils = require("./content_processor_utils.js");
37
37
  * SPDX-License-Identifier: Apache-2.0
38
38
  */
39
39
  class ContentRequestProcessor {
40
+ /**
41
+ * Fills {@link LlmRequest.contents} based on the session event history and
42
+ * agent configuration.
43
+ *
44
+ * @param invocationContext - The current invocation context.
45
+ * @param llmRequest - The request whose contents field will be populated.
46
+ */
40
47
  // eslint-disable-next-line require-yield
41
48
  async *runAsync(invocationContext, llmRequest) {
42
49
  const agent = invocationContext.agent;
@@ -34,9 +34,21 @@ var import_base_plugin = require("../../plugins/base_plugin.js");
34
34
  * SPDX-License-Identifier: Apache-2.0
35
35
  */
36
36
  class ContextCompactorRequestProcessor {
37
+ /**
38
+ * @param compactors - Ordered list of compactors to evaluate; the first one
39
+ * that reports it should compact will perform the compaction.
40
+ */
37
41
  constructor(compactors) {
38
42
  this.compactors = compactors;
39
43
  }
44
+ /**
45
+ * Evaluates compactors in priority order. The first compactor that indicates
46
+ * it should compact will compact the session history, fire plugin hooks, and
47
+ * yield any newly generated events. Iteration stops after one compaction.
48
+ *
49
+ * @param invocationContext - The current invocation context.
50
+ * @param _llmRequest - Unused; present to satisfy the {@link BaseLlmRequestProcessor} interface.
51
+ */
40
52
  async *runAsync(invocationContext, _llmRequest) {
41
53
  for (const compactor of this.compactors) {
42
54
  const shouldCompact = await Promise.resolve(
@@ -36,6 +36,13 @@ var import_base_llm_processor = require("./base_llm_processor.js");
36
36
  * SPDX-License-Identifier: Apache-2.0
37
37
  */
38
38
  class IdentityLlmRequestProcessor extends import_base_llm_processor.BaseLlmRequestProcessor {
39
+ /**
40
+ * Appends agent name and description as identity instructions to the system
41
+ * prompt of the request.
42
+ *
43
+ * @param invocationContext - The current invocation context.
44
+ * @param llmRequest - The request object to append instructions to.
45
+ */
39
46
  // eslint-disable-next-line require-yield
40
47
  async *runAsync(invocationContext, llmRequest) {
41
48
  const agent = invocationContext.agent;
@@ -75,6 +75,11 @@ class InstructionsLlmRequestProcessor extends import_base_llm_processor.BaseLlmR
75
75
  }
76
76
  (0, import_llm_request.appendInstructions)(llmRequest, [instructionWithState]);
77
77
  }
78
+ if (agent.outputSchema && agent.tools && agent.tools.length > 0) {
79
+ (0, import_llm_request.appendInstructions)(llmRequest, [
80
+ 'To output the final result, you must call the "set_model_response" function with the appropriate values. Do not output anything else.'
81
+ ]);
82
+ }
78
83
  }
79
84
  }
80
85
  const INSTRUCTIONS_LLM_REQUEST_PROCESSOR = new InstructionsLlmRequestProcessor();
@@ -40,7 +40,15 @@ var import_base_llm_processor = require("./base_llm_processor.js");
40
40
  * SPDX-License-Identifier: Apache-2.0
41
41
  */
42
42
  class RequestConfirmationLlmRequestProcessor extends import_base_llm_processor.BaseLlmRequestProcessor {
43
- /** Handles tool confirmation information to build the LLM request. */
43
+ /**
44
+ * Resumes tool calls that were paused for user confirmation, re-invoking
45
+ * them with the confirmed or denied decision before the next LLM turn.
46
+ *
47
+ * @param invocationContext - The current invocation context, including the
48
+ * session event history used to locate pending confirmation responses.
49
+ * @yields Function response events for tools that have been confirmed and
50
+ * are ready to resume.
51
+ */
44
52
  async *runAsync(invocationContext) {
45
53
  const agent = invocationContext.agent;
46
54
  if (!(0, import_llm_agent.isLlmAgent)(agent)) {
@@ -38,7 +38,13 @@ var import_base_llm_processor = require("./base_llm_processor.js");
38
38
  * SPDX-License-Identifier: Apache-2.0
39
39
  */
40
40
  class ToolFilterRequestProcessor extends import_base_llm_processor.BaseLlmRequestProcessor {
41
- /** Filters the set of tools on the request based on plugins. */
41
+ /**
42
+ * Invokes plugin-based tool filtering and updates {@link LlmRequest.allowedTools}
43
+ * with the reduced tool set if any plugin returns a filtered result.
44
+ *
45
+ * @param invocationContext - The current invocation context.
46
+ * @param llmRequest - The request whose allowed tools may be restricted.
47
+ */
42
48
  // eslint-disable-next-line require-yield
43
49
  async *runAsync(invocationContext, llmRequest) {
44
50
  const agent = invocationContext.agent;
@@ -34,6 +34,7 @@ var import_base_llm_processor = require("../agents/processors/base_llm_processor
34
34
  var import_readonly_context = require("../agents/readonly_context.js");
35
35
  var import_event = require("../events/event.js");
36
36
  var import_state = require("../sessions/state.js");
37
+ var import_case_utils = require("../utils/case_utils.js");
37
38
  var import_auth_handler = require("./auth_handler.js");
38
39
  /**
39
40
  * @license
@@ -47,17 +48,15 @@ async function storeAuthAndCollectResumeTargets(events, authFcIds, authResponses
47
48
  const eventFunctionCalls = (0, import_event.getFunctionCalls)(event);
48
49
  for (const functionCall of eventFunctionCalls) {
49
50
  if (functionCall.id && authFcIds.has(functionCall.id) && functionCall.name === import_functions.REQUEST_EUC_FUNCTION_CALL_NAME) {
50
- const args = functionCall.args;
51
- if (args && args.authConfig) {
52
- requestedAuthConfigById[functionCall.id] = args.authConfig;
51
+ const args = (0, import_case_utils.camelCaseKeys)(functionCall.args);
52
+ const authConfig = args == null ? void 0 : args.authConfig;
53
+ if (authConfig) {
54
+ requestedAuthConfigById[functionCall.id] = authConfig;
53
55
  }
54
56
  }
55
57
  }
56
58
  }
57
59
  for (const fcId of authFcIds) {
58
- if (!(fcId in authResponses)) {
59
- continue;
60
- }
61
60
  const authConfig = authResponses[fcId];
62
61
  const requestedAuthConfig = requestedAuthConfigById[fcId];
63
62
  if (requestedAuthConfig && requestedAuthConfig.credentialKey) {
@@ -75,12 +74,15 @@ async function storeAuthAndCollectResumeTargets(events, authFcIds, authResponses
75
74
  const eventFunctionCalls = (0, import_event.getFunctionCalls)(event);
76
75
  for (const functionCall of eventFunctionCalls) {
77
76
  if (functionCall.id === fcId && functionCall.name === import_functions.REQUEST_EUC_FUNCTION_CALL_NAME) {
78
- const args = functionCall.args;
79
- if (args && args.functionCallId) {
80
- if (args.functionCallId.startsWith(TOOLSET_AUTH_CREDENTIAL_ID_PREFIX)) {
77
+ const args = (0, import_case_utils.camelCaseKeys)(
78
+ functionCall.args
79
+ );
80
+ const functionCallId = args == null ? void 0 : args.functionCallId;
81
+ if (functionCallId) {
82
+ if (functionCallId.startsWith(TOOLSET_AUTH_CREDENTIAL_ID_PREFIX)) {
81
83
  continue;
82
84
  }
83
- toolsToResume.add(args.functionCallId);
85
+ toolsToResume.add(functionCallId);
84
86
  }
85
87
  }
86
88
  }
@@ -172,7 +172,7 @@ function validateDiscoveryUrl(urlStr) {
172
172
  return false;
173
173
  }
174
174
  const host = normaliseHostname(url.hostname.toLowerCase());
175
- if (host === "localhost" || host === "127.0.0.1" || host === "[::1]" || host === "0.0.0.0" || host.startsWith("10.") || host.startsWith("192.168.") || host.startsWith("169.254.")) {
175
+ if (host === "localhost" || host === "metadata.google.internal" || host === "metadata.goog" || host.startsWith("127.") || host === "[::1]" || host === "0.0.0.0" || host.startsWith("10.") || host.startsWith("192.168.") || host.startsWith("169.254.")) {
176
176
  import_logger.logger.warn(`Unsafe host for discovery URL: ${host}`);
177
177
  return false;
178
178
  }