@google/adk 0.2.0 → 0.2.2

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 (75) hide show
  1. package/README.md +1 -7
  2. package/dist/cjs/agents/base_agent.js +14 -2
  3. package/dist/cjs/agents/content_processor_utils.js +2 -2
  4. package/dist/cjs/agents/functions.js +6 -3
  5. package/dist/cjs/agents/llm_agent.js +331 -4
  6. package/dist/cjs/auth/exchanger/base_credential_exchanger.js +40 -0
  7. package/dist/cjs/auth/exchanger/credential_exchanger_registry.js +59 -0
  8. package/dist/cjs/code_executors/code_execution_utils.js +2 -2
  9. package/dist/cjs/code_executors/code_executor_context.js +2 -2
  10. package/dist/cjs/common.js +7 -0
  11. package/dist/cjs/index.js +63 -5
  12. package/dist/cjs/index.js.map +4 -4
  13. package/dist/cjs/models/base_llm.js +16 -4
  14. package/dist/cjs/runner/runner.js +10 -1
  15. package/dist/cjs/sessions/in_memory_session_service.js +3 -3
  16. package/dist/cjs/sessions/state.js +1 -1
  17. package/dist/cjs/tools/agent_tool.js +2 -2
  18. package/dist/cjs/tools/mcp/mcp_session_manager.js +7 -1
  19. package/dist/cjs/utils/gemini_schema_util.js +16 -0
  20. package/dist/cjs/version.js +2 -2
  21. package/dist/esm/agents/base_agent.js +12 -1
  22. package/dist/esm/agents/content_processor_utils.js +2 -2
  23. package/dist/esm/agents/functions.js +6 -3
  24. package/dist/esm/agents/llm_agent.js +330 -4
  25. package/dist/esm/auth/exchanger/base_credential_exchanger.js +10 -0
  26. package/dist/esm/auth/exchanger/credential_exchanger_registry.js +29 -0
  27. package/dist/esm/code_executors/code_execution_utils.js +2 -2
  28. package/dist/esm/code_executors/code_executor_context.js +2 -2
  29. package/dist/esm/common.js +6 -2
  30. package/dist/esm/index.js +63 -5
  31. package/dist/esm/index.js.map +4 -4
  32. package/dist/esm/models/base_llm.js +14 -3
  33. package/dist/esm/runner/runner.js +10 -1
  34. package/dist/esm/sessions/in_memory_session_service.js +3 -3
  35. package/dist/esm/sessions/state.js +1 -1
  36. package/dist/esm/tools/agent_tool.js +2 -2
  37. package/dist/esm/tools/function_tool.js +3 -1
  38. package/dist/esm/tools/mcp/mcp_session_manager.js +7 -1
  39. package/dist/esm/utils/gemini_schema_util.js +16 -0
  40. package/dist/esm/version.js +2 -2
  41. package/dist/types/agents/base_agent.d.ts +15 -0
  42. package/dist/types/agents/functions.d.ts +2 -0
  43. package/dist/types/agents/llm_agent.d.ts +23 -0
  44. package/dist/types/auth/exchanger/base_credential_exchanger.d.ts +32 -0
  45. package/dist/types/auth/exchanger/credential_exchanger_registry.d.ts +28 -0
  46. package/dist/types/code_executors/code_executor_context.d.ts +0 -5
  47. package/dist/types/common.d.ts +3 -2
  48. package/dist/types/models/base_llm.d.ts +16 -0
  49. package/dist/types/sessions/in_memory_session_service.d.ts +0 -5
  50. package/dist/types/sessions/state.d.ts +2 -2
  51. package/dist/types/tools/function_tool.d.ts +3 -3
  52. package/dist/types/tools/tool_confirmation.d.ts +1 -1
  53. package/dist/types/utils/gemini_schema_util.d.ts +2 -2
  54. package/dist/types/version.d.ts +2 -2
  55. package/dist/web/agents/base_agent.js +12 -1
  56. package/dist/web/agents/content_processor_utils.js +2 -2
  57. package/dist/web/agents/functions.js +6 -3
  58. package/dist/web/agents/llm_agent.js +315 -4
  59. package/dist/web/auth/exchanger/base_credential_exchanger.js +10 -0
  60. package/dist/web/auth/exchanger/credential_exchanger_registry.js +29 -0
  61. package/dist/web/code_executors/code_execution_utils.js +2 -2
  62. package/dist/web/code_executors/code_executor_context.js +2 -2
  63. package/dist/web/common.js +6 -2
  64. package/dist/web/index.js +6 -1
  65. package/dist/web/index.js.map +4 -4
  66. package/dist/web/models/base_llm.js +14 -3
  67. package/dist/web/runner/runner.js +10 -1
  68. package/dist/web/sessions/in_memory_session_service.js +3 -3
  69. package/dist/web/sessions/state.js +1 -1
  70. package/dist/web/tools/agent_tool.js +2 -2
  71. package/dist/web/tools/function_tool.js +3 -1
  72. package/dist/web/tools/mcp/mcp_session_manager.js +7 -1
  73. package/dist/web/utils/gemini_schema_util.js +16 -0
  74. package/dist/web/version.js +2 -2
  75. package/package.json +3 -1
@@ -24,7 +24,8 @@ var __copyProps = (to, from, except, desc) => {
24
24
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
25
25
  var base_llm_exports = {};
26
26
  __export(base_llm_exports, {
27
- BaseLlm: () => BaseLlm
27
+ BaseLlm: () => BaseLlm,
28
+ isBaseLlm: () => isBaseLlm
28
29
  });
29
30
  module.exports = __toCommonJS(base_llm_exports);
30
31
  var import_client_labels = require("../utils/client_labels.js");
@@ -33,6 +34,12 @@ var import_client_labels = require("../utils/client_labels.js");
33
34
  * Copyright 2025 Google LLC
34
35
  * SPDX-License-Identifier: Apache-2.0
35
36
  */
37
+ var _a;
38
+ const BASE_MODEL_SYMBOL = Symbol.for("google.adk.baseModel");
39
+ function isBaseLlm(obj) {
40
+ return typeof obj === "object" && obj !== null && BASE_MODEL_SYMBOL in obj && obj[BASE_MODEL_SYMBOL] === true;
41
+ }
42
+ _a = BASE_MODEL_SYMBOL;
36
43
  class BaseLlm {
37
44
  /**
38
45
  * Creates an instance of BaseLLM.
@@ -41,6 +48,10 @@ class BaseLlm {
41
48
  * gemini-1.5-flash-001.
42
49
  */
43
50
  constructor({ model }) {
51
+ /**
52
+ * A unique symbol to identify BaseLlm classes.
53
+ */
54
+ this[_a] = true;
44
55
  this.model = model;
45
56
  }
46
57
  get trackingHeaders() {
@@ -57,7 +68,7 @@ class BaseLlm {
57
68
  * @param llmRequest LlmRequest, the request to send to the LLM.
58
69
  */
59
70
  maybeAppendUserContent(llmRequest) {
60
- var _a;
71
+ var _a2;
61
72
  if (llmRequest.contents.length === 0) {
62
73
  llmRequest.contents.push({
63
74
  role: "user",
@@ -66,7 +77,7 @@ class BaseLlm {
66
77
  ]
67
78
  });
68
79
  }
69
- if (((_a = llmRequest.contents[llmRequest.contents.length - 1]) == null ? void 0 : _a.role) !== "user") {
80
+ if (((_a2 = llmRequest.contents[llmRequest.contents.length - 1]) == null ? void 0 : _a2.role) !== "user") {
70
81
  llmRequest.contents.push({
71
82
  role: "user",
72
83
  parts: [{
@@ -82,5 +93,6 @@ class BaseLlm {
82
93
  BaseLlm.supportedModels = [];
83
94
  // Annotate the CommonJS export names for ESM import in node:
84
95
  0 && (module.exports = {
85
- BaseLlm
96
+ BaseLlm,
97
+ isBaseLlm
86
98
  });
@@ -32,6 +32,7 @@ var import_api = require("@opentelemetry/api");
32
32
  var import_invocation_context = require("../agents/invocation_context.js");
33
33
  var import_llm_agent = require("../agents/llm_agent.js");
34
34
  var import_run_config = require("../agents/run_config.js");
35
+ var import_built_in_code_executor = require("../code_executors/built_in_code_executor.js");
35
36
  var import_event = require("../events/event.js");
36
37
  var import_event_actions = require("../events/event_actions.js");
37
38
  var import_plugin_manager = require("../plugins/plugin_manager.js");
@@ -77,6 +78,11 @@ class Runner {
77
78
  try {
78
79
  const session = await this.sessionService.getSession({ appName: this.appName, userId, sessionId });
79
80
  if (!session) {
81
+ if (!this.appName) {
82
+ throw new Error(
83
+ `Session lookup failed: appName must be provided in runner constructor`
84
+ );
85
+ }
80
86
  throw new Error(`Session not found: ${sessionId}`);
81
87
  }
82
88
  if (runConfig.supportCfc && this.agent instanceof import_llm_agent.LlmAgent) {
@@ -85,6 +91,9 @@ class Runner {
85
91
  throw new Error(`CFC is not supported for model: ${modelName} in agent: ${this.agent.name}`);
86
92
  }
87
93
  }
94
+ if (this.agent instanceof import_llm_agent.LlmAgent && !(this.agent.codeExecutor instanceof import_built_in_code_executor.BuiltInCodeExecutor)) {
95
+ this.agent.codeExecutor = new import_built_in_code_executor.BuiltInCodeExecutor();
96
+ }
88
97
  const invocationContext = new import_invocation_context.InvocationContext({
89
98
  artifactService: this.artifactService,
90
99
  sessionService: this.sessionService,
@@ -106,7 +115,7 @@ class Runner {
106
115
  }
107
116
  if (newMessage) {
108
117
  if (!((_a = newMessage.parts) == null ? void 0 : _a.length)) {
109
- throw new Error("No parts in the new_message.");
118
+ throw new Error("No parts in the newMessage.");
110
119
  }
111
120
  if (runConfig.saveInputBlobsAsArtifacts) {
112
121
  await this.saveArtifacts(
@@ -27,7 +27,7 @@ __export(in_memory_session_service_exports, {
27
27
  InMemorySessionService: () => InMemorySessionService
28
28
  });
29
29
  module.exports = __toCommonJS(in_memory_session_service_exports);
30
- var import_deep_clone = require("../utils/deep_clone.js");
30
+ var import_lodash = require("lodash");
31
31
  var import_env_aware_utils = require("../utils/env_aware_utils.js");
32
32
  var import_logger = require("../utils/logger.js");
33
33
  var import_base_session_service = require("./base_session_service.js");
@@ -72,7 +72,7 @@ class InMemorySessionService extends import_base_session_service.BaseSessionServ
72
72
  }
73
73
  this.sessions[appName][userId][session.id] = session;
74
74
  return Promise.resolve(
75
- this.mergeState(appName, userId, (0, import_deep_clone.deepClone)(session))
75
+ this.mergeState(appName, userId, (0, import_lodash.cloneDeep)(session))
76
76
  );
77
77
  }
78
78
  getSession({ appName, userId, sessionId, config }) {
@@ -80,7 +80,7 @@ class InMemorySessionService extends import_base_session_service.BaseSessionServ
80
80
  return Promise.resolve(void 0);
81
81
  }
82
82
  const session = this.sessions[appName][userId][sessionId];
83
- const copiedSession = (0, import_deep_clone.deepClone)(session);
83
+ const copiedSession = (0, import_lodash.cloneDeep)(session);
84
84
  if (config) {
85
85
  if (config.numRecentEvents) {
86
86
  copiedSession.events = copiedSession.events.slice(-config.numRecentEvents);
@@ -33,7 +33,7 @@ module.exports = __toCommonJS(state_exports);
33
33
  * SPDX-License-Identifier: Apache-2.0
34
34
  */
35
35
  class State {
36
- constructor(value, delta) {
36
+ constructor(value = {}, delta = {}) {
37
37
  this.value = value;
38
38
  this.delta = delta;
39
39
  }
@@ -124,8 +124,8 @@ class AgentTool extends import_base_tool.BaseTool {
124
124
  return "";
125
125
  }
126
126
  const hasOutputSchema = this.agent instanceof import_llm_agent.LlmAgent && this.agent.outputSchema;
127
- const mergetText = lastEvent.content.parts.map((part) => part.text).filter((text) => text).join("\n");
128
- return hasOutputSchema ? JSON.parse(mergetText) : mergetText;
127
+ const mergedText = lastEvent.content.parts.map((part) => part.text).filter((text) => text).join("\n");
128
+ return hasOutputSchema ? JSON.parse(mergedText) : mergedText;
129
129
  }
130
130
  }
131
131
  // Annotate the CommonJS export names for ESM import in node:
@@ -48,8 +48,14 @@ class MCPSessionManager {
48
48
  );
49
49
  break;
50
50
  case "StreamableHTTPConnectionParams":
51
+ const transportOptions = this.connectionParams.header ? {
52
+ requestInit: {
53
+ headers: this.connectionParams.header
54
+ }
55
+ } : void 0;
51
56
  await client.connect(new import_streamableHttp.StreamableHTTPClientTransport(
52
- new URL(this.connectionParams.url)
57
+ new URL(this.connectionParams.url),
58
+ transportOptions
53
59
  ));
54
60
  break;
55
61
  default:
@@ -63,6 +63,22 @@ function toGeminiSchema(mcpSchema) {
63
63
  return void 0;
64
64
  }
65
65
  function recursiveConvert(mcp) {
66
+ if (!mcp.type && mcp.anyOf && Array.isArray(mcp.anyOf)) {
67
+ const nonNullOption = mcp.anyOf.find((opt) => {
68
+ const t = opt.type;
69
+ return t !== "null" && t !== "NULL";
70
+ });
71
+ if (nonNullOption) {
72
+ mcp = nonNullOption;
73
+ }
74
+ }
75
+ if (!mcp.type) {
76
+ if (mcp.properties || mcp.$ref) {
77
+ mcp.type = "object";
78
+ } else if (mcp.items) {
79
+ mcp.type = "array";
80
+ }
81
+ }
66
82
  const geminiType = toGeminiType(mcp.type);
67
83
  const geminiSchema = { type: geminiType, description: mcp.description };
68
84
  if (geminiType === import_genai.Type.OBJECT) {
@@ -29,10 +29,10 @@ __export(version_exports, {
29
29
  module.exports = __toCommonJS(version_exports);
30
30
  /**
31
31
  * @license
32
- * Copyright 2025 Google LLC
32
+ * Copyright 2026 Google LLC
33
33
  * SPDX-License-Identifier: Apache-2.0
34
34
  */
35
- const version = "0.2.0";
35
+ const version = "0.2.3";
36
36
  // Annotate the CommonJS export names for ESM import in node:
37
37
  0 && (module.exports = {
38
38
  version
@@ -3,12 +3,22 @@
3
3
  * Copyright 2025 Google LLC
4
4
  * SPDX-License-Identifier: Apache-2.0
5
5
  */
6
+ var _a;
6
7
  import { trace } from "@opentelemetry/api";
7
8
  import { createEvent } from "../events/event.js";
8
9
  import { CallbackContext } from "./callback_context.js";
9
10
  import { InvocationContext } from "./invocation_context.js";
11
+ const BASE_AGENT_SIGNATURE_SYMBOL = Symbol.for("google.adk.baseAgent");
12
+ function isBaseAgent(obj) {
13
+ return typeof obj === "object" && obj !== null && BASE_AGENT_SIGNATURE_SYMBOL in obj && obj[BASE_AGENT_SIGNATURE_SYMBOL] === true;
14
+ }
15
+ _a = BASE_AGENT_SIGNATURE_SYMBOL;
10
16
  class BaseAgent {
11
17
  constructor(config) {
18
+ /**
19
+ * A unique symbol to identify ADK agent classes.
20
+ */
21
+ this[_a] = true;
12
22
  this.name = validateAgentName(config.name);
13
23
  this.description = config.description;
14
24
  this.parentAgent = config.parentAgent;
@@ -210,5 +220,6 @@ function getCannonicalCallback(callbacks) {
210
220
  }
211
221
  export {
212
222
  BaseAgent,
213
- getCannonicalCallback
223
+ getCannonicalCallback,
224
+ isBaseAgent
214
225
  };
@@ -3,8 +3,8 @@
3
3
  * Copyright 2025 Google LLC
4
4
  * SPDX-License-Identifier: Apache-2.0
5
5
  */
6
+ import { cloneDeep } from "lodash";
6
7
  import { createEvent, getFunctionCalls, getFunctionResponses } from "../events/event.js";
7
- import { deepClone } from "../utils/deep_clone.js";
8
8
  import { removeClientFunctionCallId, REQUEST_CONFIRMATION_FUNCTION_CALL_NAME, REQUEST_EUC_FUNCTION_CALL_NAME } from "./functions.js";
9
9
  function getContents(events, agentName, currentBranch) {
10
10
  var _a, _b, _c;
@@ -30,7 +30,7 @@ function getContents(events, agentName, currentBranch) {
30
30
  resultEvents = rearrangeEventsForAsyncFunctionResponsesInHistory(resultEvents);
31
31
  const contents = [];
32
32
  for (const event of resultEvents) {
33
- const content = deepClone(event.content);
33
+ const content = cloneDeep(event.content);
34
34
  removeClientFunctionCallId(content);
35
35
  contents.push(content);
36
36
  }
@@ -4,6 +4,7 @@
4
4
  * SPDX-License-Identifier: Apache-2.0
5
5
  */
6
6
  import { createUserContent } from "@google/genai";
7
+ import { isEmpty } from "lodash";
7
8
  import { createEvent, getFunctionCalls } from "../events/event.js";
8
9
  import { mergeEventActions } from "../events/event_actions.js";
9
10
  import { ToolContext } from "../tools/tool_context.js";
@@ -13,7 +14,9 @@ const AF_FUNCTION_CALL_ID_PREFIX = "adk-";
13
14
  const REQUEST_EUC_FUNCTION_CALL_NAME = "adk_request_credential";
14
15
  const REQUEST_CONFIRMATION_FUNCTION_CALL_NAME = "adk_request_confirmation";
15
16
  const functionsExportedForTestingOnly = {
16
- handleFunctionCallList
17
+ handleFunctionCallList,
18
+ generateAuthEvent,
19
+ generateRequestConfirmationEvent
17
20
  };
18
21
  function generateClientFunctionCallId() {
19
22
  return `${AF_FUNCTION_CALL_ID_PREFIX}${randomUUID()}`;
@@ -52,7 +55,7 @@ function getLongRunningFunctionCalls(functionCalls, toolsDict) {
52
55
  }
53
56
  function generateAuthEvent(invocationContext, functionResponseEvent) {
54
57
  var _a;
55
- if (!((_a = functionResponseEvent.actions) == null ? void 0 : _a.requestedAuthConfigs)) {
58
+ if (!((_a = functionResponseEvent.actions) == null ? void 0 : _a.requestedAuthConfigs) || isEmpty(functionResponseEvent.actions.requestedAuthConfigs)) {
56
59
  return void 0;
57
60
  }
58
61
  const parts = [];
@@ -88,7 +91,7 @@ function generateRequestConfirmationEvent({
88
91
  functionResponseEvent
89
92
  }) {
90
93
  var _a, _b;
91
- if (!((_a = functionResponseEvent.actions) == null ? void 0 : _a.requestedToolConfirmations)) {
94
+ if (!((_a = functionResponseEvent.actions) == null ? void 0 : _a.requestedToolConfirmations) || isEmpty(functionResponseEvent.actions.requestedToolConfirmations)) {
92
95
  return;
93
96
  }
94
97
  const parts = [];
@@ -3,15 +3,23 @@
3
3
  * Copyright 2025 Google LLC
4
4
  * SPDX-License-Identifier: Apache-2.0
5
5
  */
6
+ import { cloneDeep } from "lodash";
6
7
  import { z } from "zod";
8
+ import { BaseCodeExecutor } from "../code_executors/base_code_executor.js";
9
+ import { BuiltInCodeExecutor } from "../code_executors/built_in_code_executor.js";
10
+ import { buildCodeExecutionResultPart, buildExecutableCodePart, convertCodeExecutionParts, extractCodeAndTruncateContent } from "../code_executors/code_execution_utils.js";
11
+ import { CodeExecutorContext } from "../code_executors/code_executor_context.js";
7
12
  import { createEvent, createNewEventId, getFunctionCalls, getFunctionResponses, isFinalResponse } from "../events/event.js";
8
- import { BaseLlm } from "../models/base_llm.js";
13
+ import { createEventActions } from "../events/event_actions.js";
14
+ import { isBaseLlm } from "../models/base_llm.js";
9
15
  import { appendInstructions, setOutputSchema } from "../models/llm_request.js";
10
16
  import { LLMRegistry } from "../models/registry.js";
17
+ import { State } from "../sessions/state.js";
11
18
  import { BaseTool } from "../tools/base_tool.js";
12
19
  import { FunctionTool } from "../tools/function_tool.js";
13
20
  import { ToolConfirmation } from "../tools/tool_confirmation.js";
14
21
  import { ToolContext } from "../tools/tool_context.js";
22
+ import { base64Decode } from "../utils/env_aware_utils.js";
15
23
  import { logger } from "../utils/logger.js";
16
24
  import { BaseAgent } from "./base_agent.js";
17
25
  import { BaseLlmRequestProcessor } from "./base_llm_processor.js";
@@ -323,6 +331,321 @@ class RequestConfirmationLlmRequestProcessor extends BaseLlmRequestProcessor {
323
331
  }
324
332
  }
325
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(cloneDeep(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(cloneDeep(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();
326
649
  class LlmAgent extends BaseAgent {
327
650
  constructor(config) {
328
651
  var _a, _b, _c, _d, _e, _f, _g, _h, _i;
@@ -342,12 +665,14 @@ class LlmAgent extends BaseAgent {
342
665
  this.afterModelCallback = config.afterModelCallback;
343
666
  this.beforeToolCallback = config.beforeToolCallback;
344
667
  this.afterToolCallback = config.afterToolCallback;
668
+ this.codeExecutor = config.codeExecutor;
345
669
  this.requestProcessors = (_g = config.requestProcessors) != null ? _g : [
346
670
  BASIC_LLM_REQUEST_PROCESSOR,
347
671
  IDENTITY_LLM_REQUEST_PROCESSOR,
348
672
  INSTRUCTIONS_LLM_REQUEST_PROCESSOR,
349
673
  REQUEST_CONFIRMATION_LLM_REQUEST_PROCESSOR,
350
- CONTENT_REQUEST_PROCESSOR
674
+ CONTENT_REQUEST_PROCESSOR,
675
+ CODE_EXECUTION_REQUEST_PROCESSOR
351
676
  ];
352
677
  this.responseProcessors = (_h = config.responseProcessors) != null ? _h : [];
353
678
  const agentTransferDisabled = this.disallowTransferToParent && this.disallowTransferToPeers && !((_i = this.subAgents) == null ? void 0 : _i.length);
@@ -397,7 +722,7 @@ class LlmAgent extends BaseAgent {
397
722
  * When not set, the agent will inherit the model from its ancestor.
398
723
  */
399
724
  get canonicalModel() {
400
- if (this.model instanceof BaseLlm) {
725
+ if (isBaseLlm(this.model)) {
401
726
  return this.model;
402
727
  }
403
728
  if (typeof this.model === "string" && this.model) {
@@ -830,5 +1155,6 @@ class LlmAgent extends BaseAgent {
830
1155
  }
831
1156
  export {
832
1157
  LlmAgent,
833
- REQUEST_CONFIRMATION_LLM_REQUEST_PROCESSOR
1158
+ REQUEST_CONFIRMATION_LLM_REQUEST_PROCESSOR,
1159
+ responseProcessor
834
1160
  };
@@ -0,0 +1,10 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2025 Google LLC
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ class CredentialExchangeError extends Error {
7
+ }
8
+ export {
9
+ CredentialExchangeError
10
+ };