@google/adk 1.4.0 → 1.6.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 (213) hide show
  1. package/dist/cjs/a2a/a2a_remote_agent.js +12 -2
  2. package/dist/cjs/a2a/agent_to_a2a.js +18 -3
  3. package/dist/cjs/a2a/auth.js +65 -0
  4. package/dist/cjs/a2a/event_converter_utils.js +47 -18
  5. package/dist/cjs/a2a/metadata_converter_utils.js +1 -1
  6. package/dist/cjs/agents/base_agent.js +39 -0
  7. package/dist/cjs/agents/functions.js +26 -28
  8. package/dist/cjs/agents/llm_agent.js +4 -2
  9. package/dist/cjs/agents/loop_agent.js +15 -3
  10. package/dist/cjs/agents/processors/basic_llm_request_processor.js +3 -2
  11. package/dist/cjs/agents/processors/content_processor_utils.js +2 -1
  12. package/dist/cjs/agents/processors/content_request_processor.js +2 -21
  13. package/dist/cjs/agents/processors/instructions_llm_request_processor.js +3 -1
  14. package/dist/cjs/agents/routed_agent.js +31 -0
  15. package/dist/cjs/agents/run_config.js +3 -2
  16. package/dist/cjs/artifacts/in_memory_artifact_service.js +17 -9
  17. package/dist/cjs/auth/credential_service/in_memory_credential_service.js +14 -3
  18. package/dist/cjs/code_executors/unsafe_local_code_executor.js +23 -12
  19. package/dist/cjs/common.js +35 -0
  20. package/dist/cjs/context/agent_controlled_context_compactor.js +2 -11
  21. package/dist/cjs/context/anchored_context_compactor.js +127 -0
  22. package/dist/cjs/context/compaction_utils.js +64 -0
  23. package/dist/cjs/context/token_based_context_compactor.js +13 -44
  24. package/dist/cjs/events/compacted_event.js +9 -3
  25. package/dist/cjs/events/event.js +28 -0
  26. package/dist/cjs/index.js +7 -0
  27. package/dist/cjs/integrations/agent_registry/agent_registry_mcp_toolset.js +9 -1
  28. package/dist/cjs/memory/in_memory_memory_service.js +13 -2
  29. package/dist/cjs/memory/vertex_ai_memory_bank_service.js +3 -0
  30. package/dist/cjs/plugins/base_plugin.js +4 -2
  31. package/dist/cjs/plugins/global_instruction_plugin.js +97 -0
  32. package/dist/cjs/runner/runner.js +69 -23
  33. package/dist/cjs/sessions/base_session_service.js +8 -3
  34. package/dist/cjs/sessions/in_memory_session_service.js +8 -8
  35. package/dist/cjs/sessions/vertex_ai_session_service.js +22 -10
  36. package/dist/cjs/skills/loader.js +40 -6
  37. package/dist/cjs/tools/enterprise_web_search_tool.js +81 -0
  38. package/dist/cjs/tools/example_tool.js +68 -0
  39. package/dist/cjs/tools/get_user_choice_tool.js +53 -0
  40. package/dist/cjs/tools/load_web_page.js +250 -0
  41. package/dist/cjs/tools/mcp/load_mcp_resource_tool.js +140 -0
  42. package/dist/cjs/tools/mcp/mcp_session_manager.js +35 -21
  43. package/dist/cjs/tools/mcp/mcp_toolset.js +63 -0
  44. package/dist/cjs/tools/openapi_tool/openapi_spec_parser/tool_auth_handler.js +13 -10
  45. package/dist/cjs/tools/request_input_tool.js +54 -0
  46. package/dist/cjs/tools/skill/run_skill_inline_script_tool.js +54 -4
  47. package/dist/cjs/tools/skill/skill_toolset.js +4 -2
  48. package/dist/cjs/utils/branch_trie.js +41 -0
  49. package/dist/cjs/utils/crypto_shim.js +43 -0
  50. package/dist/cjs/utils/env_aware_utils.js +15 -13
  51. package/dist/cjs/utils/error_utils.js +120 -0
  52. package/dist/cjs/utils/file_utils.js +5 -2
  53. package/dist/cjs/utils/output_schema_utils.js +43 -0
  54. package/dist/cjs/utils/streaming_utils.js +5 -5
  55. package/dist/cjs/utils/vertex_ai_utils.js +3 -0
  56. package/dist/cjs/version.js +1 -1
  57. package/dist/esm/a2a/a2a_remote_agent.js +12 -2
  58. package/dist/esm/a2a/agent_to_a2a.js +18 -3
  59. package/dist/esm/a2a/auth.js +37 -0
  60. package/dist/esm/a2a/event_converter_utils.js +47 -18
  61. package/dist/esm/a2a/metadata_converter_utils.js +1 -1
  62. package/dist/esm/agents/base_agent.js +39 -0
  63. package/dist/esm/agents/functions.js +27 -24
  64. package/dist/esm/agents/llm_agent.js +6 -4
  65. package/dist/esm/agents/loop_agent.js +15 -3
  66. package/dist/esm/agents/processors/basic_llm_request_processor.js +3 -2
  67. package/dist/esm/agents/processors/content_processor_utils.js +2 -1
  68. package/dist/esm/agents/processors/content_request_processor.js +2 -21
  69. package/dist/esm/agents/processors/instructions_llm_request_processor.js +3 -1
  70. package/dist/esm/agents/routed_agent.js +31 -0
  71. package/dist/esm/agents/run_config.js +3 -2
  72. package/dist/esm/artifacts/in_memory_artifact_service.js +17 -9
  73. package/dist/esm/auth/credential_service/in_memory_credential_service.js +14 -3
  74. package/dist/esm/code_executors/unsafe_local_code_executor.js +22 -11
  75. package/dist/esm/common.js +29 -1
  76. package/dist/esm/context/agent_controlled_context_compactor.js +2 -11
  77. package/dist/esm/context/anchored_context_compactor.js +99 -0
  78. package/dist/esm/context/compaction_utils.js +38 -0
  79. package/dist/esm/context/token_based_context_compactor.js +16 -44
  80. package/dist/esm/events/compacted_event.js +7 -2
  81. package/dist/esm/events/event.js +24 -0
  82. package/dist/esm/index.js +8 -1
  83. package/dist/esm/integrations/agent_registry/agent_registry_mcp_toolset.js +9 -1
  84. package/dist/esm/memory/in_memory_memory_service.js +13 -2
  85. package/dist/esm/memory/vertex_ai_memory_bank_service.js +7 -1
  86. package/dist/esm/plugins/base_plugin.js +4 -2
  87. package/dist/esm/plugins/global_instruction_plugin.js +69 -0
  88. package/dist/esm/runner/runner.js +69 -23
  89. package/dist/esm/sessions/base_session_service.js +8 -3
  90. package/dist/esm/sessions/in_memory_session_service.js +8 -8
  91. package/dist/esm/sessions/vertex_ai_session_service.js +26 -11
  92. package/dist/esm/skills/loader.js +40 -6
  93. package/dist/esm/tools/enterprise_web_search_tool.js +55 -0
  94. package/dist/esm/tools/example_tool.js +42 -0
  95. package/dist/esm/tools/get_user_choice_tool.js +25 -0
  96. package/dist/esm/tools/load_web_page.js +221 -0
  97. package/dist/esm/tools/mcp/load_mcp_resource_tool.js +114 -0
  98. package/dist/esm/tools/mcp/mcp_session_manager.js +35 -21
  99. package/dist/esm/tools/mcp/mcp_toolset.js +63 -0
  100. package/dist/esm/tools/openapi_tool/openapi_spec_parser/tool_auth_handler.js +13 -10
  101. package/dist/esm/tools/request_input_tool.js +26 -0
  102. package/dist/esm/tools/skill/run_skill_inline_script_tool.js +53 -4
  103. package/dist/esm/tools/skill/skill_toolset.js +4 -2
  104. package/dist/esm/utils/branch_trie.js +13 -0
  105. package/dist/esm/utils/crypto_shim.js +15 -0
  106. package/dist/esm/utils/env_aware_utils.js +15 -13
  107. package/dist/esm/utils/error_utils.js +92 -0
  108. package/dist/esm/utils/file_utils.js +5 -2
  109. package/dist/esm/utils/output_schema_utils.js +15 -0
  110. package/dist/esm/utils/streaming_utils.js +1 -1
  111. package/dist/esm/utils/vertex_ai_utils.js +2 -0
  112. package/dist/esm/version.js +1 -1
  113. package/dist/types/a2a/a2a_remote_agent.d.ts +5 -1
  114. package/dist/types/a2a/agent_to_a2a.d.ts +38 -0
  115. package/dist/types/a2a/auth.d.ts +30 -0
  116. package/dist/types/a2a/event_converter_utils.d.ts +4 -1
  117. package/dist/types/agents/base_agent.d.ts +29 -1
  118. package/dist/types/agents/functions.d.ts +1 -9
  119. package/dist/types/agents/llm_agent.d.ts +5 -1
  120. package/dist/types/agents/loop_agent.d.ts +2 -2
  121. package/dist/types/agents/routed_agent.d.ts +24 -1
  122. package/dist/types/agents/run_config.d.ts +1 -1
  123. package/dist/types/auth/credential_service/in_memory_credential_service.d.ts +11 -0
  124. package/dist/types/code_executors/unsafe_local_code_executor.d.ts +5 -1
  125. package/dist/types/common.d.ts +11 -2
  126. package/dist/types/context/agent_controlled_context_compactor.d.ts +0 -1
  127. package/dist/types/context/anchored_context_compactor.d.ts +35 -0
  128. package/dist/types/context/compaction_utils.d.ts +23 -0
  129. package/dist/types/context/token_based_context_compactor.d.ts +0 -1
  130. package/dist/types/events/compacted_event.d.ts +10 -0
  131. package/dist/types/events/event.d.ts +13 -0
  132. package/dist/types/index.d.ts +5 -3
  133. package/dist/types/memory/in_memory_memory_service.d.ts +11 -0
  134. package/dist/types/plugins/base_plugin.d.ts +4 -2
  135. package/dist/types/plugins/global_instruction_plugin.d.ts +38 -0
  136. package/dist/types/runner/runner.d.ts +1 -1
  137. package/dist/types/sessions/base_session_service.d.ts +8 -0
  138. package/dist/types/sessions/in_memory_session_service.d.ts +9 -0
  139. package/dist/types/sessions/vertex_ai_session_service.d.ts +19 -1
  140. package/dist/types/skills/loader.d.ts +5 -0
  141. package/dist/types/tools/enterprise_web_search_tool.d.ts +26 -0
  142. package/dist/types/tools/example_tool.d.ts +21 -0
  143. package/dist/types/tools/get_user_choice_tool.d.ts +14 -0
  144. package/dist/types/tools/load_web_page.d.ts +33 -0
  145. package/dist/types/tools/mcp/load_mcp_resource_tool.d.ts +26 -0
  146. package/dist/types/tools/mcp/mcp_toolset.d.ts +27 -0
  147. package/dist/types/tools/request_input_tool.d.ts +15 -0
  148. package/dist/types/tools/skill/run_skill_inline_script_tool.d.ts +25 -0
  149. package/dist/types/tools/skill/skill_toolset.d.ts +9 -0
  150. package/dist/types/utils/branch_trie.d.ts +14 -0
  151. package/dist/types/utils/crypto_shim.d.ts +16 -0
  152. package/dist/types/utils/env_aware_utils.d.ts +23 -0
  153. package/dist/types/utils/error_utils.d.ts +18 -0
  154. package/dist/types/utils/output_schema_utils.d.ts +18 -0
  155. package/dist/types/utils/vertex_ai_utils.d.ts +1 -0
  156. package/dist/types/version.d.ts +1 -1
  157. package/dist/web/a2a/a2a_remote_agent.js +12 -2
  158. package/dist/web/a2a/agent_to_a2a.js +18 -3
  159. package/dist/web/a2a/auth.js +37 -0
  160. package/dist/web/a2a/event_converter_utils.js +47 -18
  161. package/dist/web/a2a/metadata_converter_utils.js +1 -1
  162. package/dist/web/agents/base_agent.js +39 -0
  163. package/dist/web/agents/functions.js +27 -24
  164. package/dist/web/agents/llm_agent.js +6 -4
  165. package/dist/web/agents/loop_agent.js +27 -3
  166. package/dist/web/agents/processors/basic_llm_request_processor.js +3 -2
  167. package/dist/web/agents/processors/content_processor_utils.js +2 -1
  168. package/dist/web/agents/processors/content_request_processor.js +2 -21
  169. package/dist/web/agents/processors/instructions_llm_request_processor.js +3 -1
  170. package/dist/web/agents/routed_agent.js +31 -0
  171. package/dist/web/agents/run_config.js +8 -3
  172. package/dist/web/artifacts/in_memory_artifact_service.js +17 -9
  173. package/dist/web/auth/credential_service/in_memory_credential_service.js +14 -3
  174. package/dist/web/code_executors/unsafe_local_code_executor.js +22 -11
  175. package/dist/web/common.js +29 -1
  176. package/dist/web/context/agent_controlled_context_compactor.js +2 -11
  177. package/dist/web/context/anchored_context_compactor.js +117 -0
  178. package/dist/web/context/compaction_utils.js +38 -0
  179. package/dist/web/context/token_based_context_compactor.js +16 -44
  180. package/dist/web/events/compacted_event.js +7 -2
  181. package/dist/web/events/event.js +24 -0
  182. package/dist/web/index.js +8 -1
  183. package/dist/web/integrations/agent_registry/agent_registry_mcp_toolset.js +9 -1
  184. package/dist/web/memory/in_memory_memory_service.js +13 -2
  185. package/dist/web/memory/vertex_ai_memory_bank_service.js +7 -1
  186. package/dist/web/plugins/base_plugin.js +4 -2
  187. package/dist/web/plugins/global_instruction_plugin.js +67 -0
  188. package/dist/web/runner/runner.js +65 -22
  189. package/dist/web/sessions/base_session_service.js +8 -3
  190. package/dist/web/sessions/in_memory_session_service.js +8 -8
  191. package/dist/web/sessions/vertex_ai_session_service.js +24 -11
  192. package/dist/web/skills/loader.js +40 -6
  193. package/dist/web/tools/enterprise_web_search_tool.js +55 -0
  194. package/dist/web/tools/example_tool.js +42 -0
  195. package/dist/web/tools/get_user_choice_tool.js +25 -0
  196. package/dist/web/tools/load_web_page.js +221 -0
  197. package/dist/web/tools/mcp/load_mcp_resource_tool.js +107 -0
  198. package/dist/web/tools/mcp/mcp_session_manager.js +35 -21
  199. package/dist/web/tools/mcp/mcp_toolset.js +63 -0
  200. package/dist/web/tools/openapi_tool/openapi_spec_parser/tool_auth_handler.js +13 -10
  201. package/dist/web/tools/request_input_tool.js +26 -0
  202. package/dist/web/tools/skill/run_skill_inline_script_tool.js +51 -4
  203. package/dist/web/tools/skill/skill_toolset.js +4 -2
  204. package/dist/web/utils/branch_trie.js +13 -0
  205. package/dist/web/utils/crypto_shim.js +15 -0
  206. package/dist/web/utils/env_aware_utils.js +15 -13
  207. package/dist/web/utils/error_utils.js +92 -0
  208. package/dist/web/utils/file_utils.js +5 -2
  209. package/dist/web/utils/output_schema_utils.js +15 -0
  210. package/dist/web/utils/streaming_utils.js +1 -1
  211. package/dist/web/utils/vertex_ai_utils.js +2 -0
  212. package/dist/web/version.js +1 -1
  213. package/package.json +1 -1
@@ -8,12 +8,23 @@ const require = topLevelCreateRequire(import.meta.url);
8
8
  class InMemoryMemoryService {
9
9
  constructor() {
10
10
  this.memories = [];
11
- this.sessionEvents = {};
11
+ /**
12
+ * A map from user key to a map from session ID to events.
13
+ *
14
+ * The inner map is keyed by `session.id`, which arrives off the request path
15
+ * and contains no `/`, so it can be exactly `__proto__`. On a plain object
16
+ * literal that key would reach the inherited `__proto__` setter and
17
+ * re-parent the map instead of creating an own property, silently dropping
18
+ * the session from the `Object.values` scan in `searchMemory`. The outer key
19
+ * always contains a `/` (see `getUserKey`) and cannot collide, but is
20
+ * created the same way for consistency.
21
+ */
22
+ this.sessionEvents = /* @__PURE__ */ Object.create(null);
12
23
  }
13
24
  async addSessionToMemory(session) {
14
25
  const userKey = getUserKey(session.appName, session.userId);
15
26
  if (!this.sessionEvents[userKey]) {
16
- this.sessionEvents[userKey] = {};
27
+ this.sessionEvents[userKey] = /* @__PURE__ */ Object.create(null);
17
28
  }
18
29
  this.sessionEvents[userKey][session.id] = session.events.filter(
19
30
  (event) => {
@@ -24,7 +24,10 @@ var __spreadValues = (a, b) => {
24
24
  import { Client } from "@google-cloud/vertexai";
25
25
  import { createUserContent } from "@google/genai";
26
26
  import { logger } from "../utils/logger.js";
27
- import { getExpressModeApiKey } from "../utils/vertex_ai_utils.js";
27
+ import {
28
+ EXPRESS_MODE_UNSUPPORTED_MESSAGE,
29
+ getExpressModeApiKey
30
+ } from "../utils/vertex_ai_utils.js";
28
31
  const GENERATE_MEMORIES_KNOWN_FIELDS = [
29
32
  "disableConsolidation",
30
33
  "waitForCompletion",
@@ -105,6 +108,9 @@ class VertexAiMemoryBankService {
105
108
  if (options.client) {
106
109
  this.memories = options.client.agentEnginesInternal.memories;
107
110
  } else {
111
+ if (this.expressModeApiKey && (!this.projectId || !this.location)) {
112
+ throw new Error(EXPRESS_MODE_UNSUPPORTED_MESSAGE);
113
+ }
108
114
  const client = new Client({
109
115
  project: this.projectId,
110
116
  location: this.location
@@ -73,8 +73,10 @@ class BasePlugin {
73
73
  * @param params.invocationContext The context for the entire invocation.
74
74
  * @param params.event The event raised by the runner.
75
75
  * @returns An optional value. A non-`undefined` return may be used by the
76
- * framework to modify or replace the response. Returning `undefined`
77
- * allows the original response to be used.
76
+ * framework to modify or replace the response. Copy `params.event` when
77
+ * constructing a replacement to preserve fields that are not being
78
+ * modified, such as event actions. Returning `undefined` allows the
79
+ * original response to be used.
78
80
  */
79
81
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
80
82
  async onEventCallback(params) {
@@ -0,0 +1,67 @@
1
+ import {createRequire as topLevelCreateRequire} from 'module';
2
+ const require = topLevelCreateRequire(import.meta.url);
3
+ /**
4
+ * @license
5
+ * Copyright 2026 Google LLC
6
+ * SPDX-License-Identifier: Apache-2.0
7
+ */
8
+ import { injectSessionState } from "../agents/instructions.js";
9
+ import { ReadonlyContext } from "../agents/readonly_context.js";
10
+ import { BasePlugin } from "./base_plugin.js";
11
+ class GlobalInstructionPlugin extends BasePlugin {
12
+ /**
13
+ * Initializes the GlobalInstructionPlugin.
14
+ *
15
+ * @param globalInstruction The instruction to apply globally. Can be a string
16
+ * or an InstructionProvider function that takes ReadonlyContext and
17
+ * returns a string (sync or async).
18
+ * @param name The name of the plugin (defaults to 'global_instruction').
19
+ */
20
+ constructor(globalInstruction, name = "global_instruction") {
21
+ super(name);
22
+ this.globalInstruction = globalInstruction;
23
+ }
24
+ async beforeModelCallback(params) {
25
+ if (!this.globalInstruction) {
26
+ return;
27
+ }
28
+ const readonlyContext = new ReadonlyContext(
29
+ params.callbackContext.invocationContext
30
+ );
31
+ const finalGlobalInstruction = await this.resolveGlobalInstruction(readonlyContext);
32
+ if (!finalGlobalInstruction) {
33
+ return;
34
+ }
35
+ if (!params.llmRequest.config) {
36
+ params.llmRequest.config = {};
37
+ }
38
+ const existingInstruction = params.llmRequest.config.systemInstruction;
39
+ if (!existingInstruction || Array.isArray(existingInstruction) && existingInstruction.length === 0) {
40
+ params.llmRequest.config.systemInstruction = finalGlobalInstruction;
41
+ return;
42
+ }
43
+ if (typeof existingInstruction === "string") {
44
+ params.llmRequest.config.systemInstruction = "".concat(finalGlobalInstruction, "\n\n").concat(existingInstruction);
45
+ } else if (Array.isArray(existingInstruction)) {
46
+ params.llmRequest.config.systemInstruction = [
47
+ finalGlobalInstruction,
48
+ ...existingInstruction
49
+ ];
50
+ } else {
51
+ params.llmRequest.config.systemInstruction = [
52
+ finalGlobalInstruction,
53
+ existingInstruction
54
+ ];
55
+ }
56
+ return;
57
+ }
58
+ async resolveGlobalInstruction(readonlyContext) {
59
+ if (typeof this.globalInstruction === "string") {
60
+ return await injectSessionState(this.globalInstruction, readonlyContext);
61
+ }
62
+ return await this.globalInstruction(readonlyContext);
63
+ }
64
+ }
65
+ export {
66
+ GlobalInstructionPlugin
67
+ };
@@ -191,7 +191,7 @@ class Runner {
191
191
  this,
192
192
  function() {
193
193
  return __asyncGenerator(this, null, function* () {
194
- var _a2, _b, _c, _d, _e, _f, _g, _h, _i, _j;
194
+ var _a2, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k;
195
195
  const session = yield new __await(this.sessionService.getSession({
196
196
  appName: this.appName,
197
197
  userId,
@@ -252,7 +252,7 @@ class Runner {
252
252
  throw new Error("No parts in the newMessage.");
253
253
  }
254
254
  if (runConfig.saveInputBlobsAsArtifacts) {
255
- yield new __await(this.saveArtifacts(
255
+ newMessage = yield new __await(this.saveArtifacts(
256
256
  invocationContext.invocationId,
257
257
  session.userId,
258
258
  session.id,
@@ -310,21 +310,27 @@ class Runner {
310
310
  if ((_h = params.abortSignal) == null ? void 0 : _h.aborted) {
311
311
  return;
312
312
  }
313
- if (!event.partial) {
314
- yield new __await(this.sessionService.appendEvent({ session, event }));
315
- }
316
313
  const modifiedEvent = yield new __await(this.pluginManager.runOnEventCallback({
317
314
  invocationContext,
318
315
  event
319
316
  }));
320
- if ((_i = params.abortSignal) == null ? void 0 : _i.aborted) {
321
- return;
317
+ const outputEvent = modifiedEvent ? __spreadProps(__spreadValues({}, modifiedEvent), {
318
+ id: event.id,
319
+ invocationId: event.invocationId,
320
+ timestamp: event.timestamp,
321
+ author: modifiedEvent.author || event.author,
322
+ branch: (_i = modifiedEvent.branch) != null ? _i : event.branch
323
+ }) : event;
324
+ if (!event.partial) {
325
+ yield new __await(this.sessionService.appendEvent({
326
+ session,
327
+ event: outputEvent
328
+ }));
322
329
  }
323
- if (modifiedEvent) {
324
- yield modifiedEvent;
325
- } else {
326
- yield event;
330
+ if ((_j = params.abortSignal) == null ? void 0 : _j.aborted) {
331
+ return;
327
332
  }
333
+ yield outputEvent;
328
334
  }
329
335
  } catch (temp) {
330
336
  error = [temp];
@@ -337,7 +343,7 @@ class Runner {
337
343
  }
338
344
  }
339
345
  yield new __await(this.pluginManager.runAfterRunCallback({ invocationContext }));
340
- if ((_j = params.abortSignal) == null ? void 0 : _j.aborted) {
346
+ if ((_k = params.abortSignal) == null ? void 0 : _k.aborted) {
341
347
  return;
342
348
  }
343
349
  }
@@ -354,7 +360,7 @@ class Runner {
354
360
  }
355
361
  /**
356
362
  * Saves artifacts from the message parts and replaces the inline data with
357
- * a file name placeholder.
363
+ * a file name placeholder and optional file reference.
358
364
  *
359
365
  * @param invocationId The current invocation ID.
360
366
  * @param userId The user ID of the session.
@@ -364,27 +370,64 @@ class Runner {
364
370
  async saveArtifacts(invocationId, userId, sessionId, message) {
365
371
  var _a2;
366
372
  if (!this.artifactService || !((_a2 = message.parts) == null ? void 0 : _a2.length)) {
367
- return;
373
+ return message;
368
374
  }
369
375
  const sessionKey = {
370
376
  appName: this.appName,
371
377
  userId,
372
378
  sessionId
373
379
  };
380
+ const newParts = [];
381
+ let modified = false;
374
382
  for (let i = 0; i < message.parts.length; i++) {
375
383
  const part = message.parts[i];
376
384
  if (!part.inlineData) {
385
+ newParts.push(part);
377
386
  continue;
378
387
  }
379
- const fileName = "artifact_".concat(invocationId, "_").concat(i);
380
- await this.artifactService.saveArtifact(__spreadProps(__spreadValues({}, sessionKey), {
381
- filename: fileName,
382
- artifact: part
383
- }));
384
- message.parts[i] = createPartFromText(
385
- "Uploaded file: ".concat(fileName, ". It is saved into artifacts")
386
- );
388
+ try {
389
+ const inlineData = part.inlineData;
390
+ const fileName = inlineData.displayName || "artifact_".concat(invocationId, "_").concat(i);
391
+ const version = await this.artifactService.saveArtifact(__spreadProps(__spreadValues({}, sessionKey), {
392
+ filename: fileName,
393
+ artifact: part
394
+ }));
395
+ newParts.push(createPartFromText('[Uploaded Artifact: "'.concat(fileName, '"]')));
396
+ try {
397
+ const artifactVersion = await this.artifactService.getArtifactVersion(
398
+ __spreadProps(__spreadValues({}, sessionKey), {
399
+ filename: fileName,
400
+ version
401
+ })
402
+ );
403
+ if ((artifactVersion == null ? void 0 : artifactVersion.canonicalUri) && /^(gs|https?):/i.test(artifactVersion.canonicalUri)) {
404
+ newParts.push({
405
+ fileData: {
406
+ fileUri: artifactVersion.canonicalUri,
407
+ mimeType: artifactVersion.mimeType || inlineData.mimeType || "",
408
+ displayName: fileName
409
+ }
410
+ });
411
+ }
412
+ } catch (error) {
413
+ logger.warn(
414
+ "Failed to resolve artifact version for ".concat(fileName, ":"),
415
+ error
416
+ );
417
+ }
418
+ modified = true;
419
+ logger.info("Successfully saved artifact: ".concat(fileName));
420
+ } catch (error) {
421
+ logger.error("Failed to save artifact for part ".concat(i, ":"), error);
422
+ newParts.push(part);
423
+ }
387
424
  }
425
+ if (!modified) {
426
+ return message;
427
+ }
428
+ return __spreadProps(__spreadValues({}, message), {
429
+ parts: newParts
430
+ });
388
431
  }
389
432
  /**
390
433
  * Determines the next agent to run to continue the session. This is primarily
@@ -61,7 +61,12 @@ class BaseSessionService {
61
61
  if (key.startsWith(State.TEMP_PREFIX)) {
62
62
  continue;
63
63
  }
64
- session.state[key] = value;
64
+ Object.defineProperty(session.state, key, {
65
+ value,
66
+ writable: true,
67
+ enumerable: true,
68
+ configurable: true
69
+ });
65
70
  }
66
71
  }
67
72
  }
@@ -70,7 +75,7 @@ function trimTempDeltaState(event) {
70
75
  return event;
71
76
  }
72
77
  const stateDelta = event.actions.stateDelta;
73
- const filteredStateDelta = {};
78
+ const filteredStateDelta = /* @__PURE__ */ Object.create(null);
74
79
  for (const [key, value] of Object.entries(stateDelta)) {
75
80
  if (!key.startsWith(State.TEMP_PREFIX)) {
76
81
  filteredStateDelta[key] = value;
@@ -80,7 +85,7 @@ function trimTempDeltaState(event) {
80
85
  return event;
81
86
  }
82
87
  function trimTempState(state) {
83
- const filteredState = {};
88
+ const filteredState = /* @__PURE__ */ Object.create(null);
84
89
  for (const [key, value] of Object.entries(state)) {
85
90
  if (!key.startsWith(State.TEMP_PREFIX)) {
86
91
  filteredState[key] = value;
@@ -25,15 +25,15 @@ class InMemorySessionService extends BaseSessionService {
25
25
  * A map from app name to a map from user ID to a map from session ID to
26
26
  * session.
27
27
  */
28
- this.sessions = {};
28
+ this.sessions = /* @__PURE__ */ Object.create(null);
29
29
  /**
30
30
  * A map from app name to a map from user ID to a map from key to the value.
31
31
  */
32
- this.userState = {};
32
+ this.userState = /* @__PURE__ */ Object.create(null);
33
33
  /**
34
34
  * A map from app name to a map from key to the value.
35
35
  */
36
- this.appState = {};
36
+ this.appState = /* @__PURE__ */ Object.create(null);
37
37
  }
38
38
  async createSession({
39
39
  appName,
@@ -52,10 +52,10 @@ class InMemorySessionService extends BaseSessionService {
52
52
  lastUpdateTime: Date.now()
53
53
  });
54
54
  if (!this.sessions[appName]) {
55
- this.sessions[appName] = {};
55
+ this.sessions[appName] = /* @__PURE__ */ Object.create(null);
56
56
  }
57
57
  if (!this.sessions[appName][userId]) {
58
- this.sessions[appName][userId] = {};
58
+ this.sessions[appName][userId] = /* @__PURE__ */ Object.create(null);
59
59
  }
60
60
  this.sessions[appName][userId][session.id] = session;
61
61
  const copiedSession = cloneDeep(session);
@@ -220,12 +220,12 @@ class InMemorySessionService extends BaseSessionService {
220
220
  if (event.actions && event.actions.stateDelta) {
221
221
  for (const key of Object.keys(event.actions.stateDelta)) {
222
222
  if (key.startsWith(State.APP_PREFIX)) {
223
- this.appState[appName] = this.appState[appName] || {};
223
+ this.appState[appName] = this.appState[appName] || /* @__PURE__ */ Object.create(null);
224
224
  this.appState[appName][key.replace(State.APP_PREFIX, "")] = event.actions.stateDelta[key];
225
225
  }
226
226
  if (key.startsWith(State.USER_PREFIX)) {
227
- this.userState[appName] = this.userState[appName] || {};
228
- this.userState[appName][userId] = this.userState[appName][userId] || {};
227
+ this.userState[appName] = this.userState[appName] || /* @__PURE__ */ Object.create(null);
228
+ this.userState[appName][userId] = this.userState[appName][userId] || /* @__PURE__ */ Object.create(null);
229
229
  this.userState[appName][userId][key.replace(State.USER_PREFIX, "")] = event.actions.stateDelta[key];
230
230
  }
231
231
  }
@@ -37,7 +37,10 @@ import { Client } from "@google-cloud/vertexai/build/src/genai/client.js";
37
37
  import { isCompactedEvent } from "../events/compacted_event.js";
38
38
  import { experimental } from "../utils/experimental.js";
39
39
  import { logger } from "../utils/logger.js";
40
- import { getExpressModeApiKey } from "../utils/vertex_ai_utils.js";
40
+ import {
41
+ EXPRESS_MODE_UNSUPPORTED_MESSAGE,
42
+ getExpressModeApiKey
43
+ } from "../utils/vertex_ai_utils.js";
41
44
  import { partialCopy } from "../utils/partial_copy.js";
42
45
  import {
43
46
  BaseSessionService,
@@ -65,16 +68,14 @@ let VertexAiSessionService = class extends BaseSessionService {
65
68
  this.location,
66
69
  options.expressModeApiKey
67
70
  );
68
- if (!options.sessions) {
69
- if (!this.expressModeApiKey && (!this.projectId || !this.location)) {
70
- throw new Error(
71
- "Either (Project ID and Location) or an expressModeApiKey is required."
72
- );
73
- }
74
- }
75
71
  if (options.sessions) {
76
72
  this.sessions = options.sessions;
77
73
  } else {
74
+ if (!this.projectId || !this.location) {
75
+ throw new Error(
76
+ this.expressModeApiKey ? EXPRESS_MODE_UNSUPPORTED_MESSAGE : "Project ID and Location are required."
77
+ );
78
+ }
78
79
  const client = new Client({
79
80
  project: this.projectId,
80
81
  location: this.location
@@ -98,19 +99,31 @@ let VertexAiSessionService = class extends BaseSessionService {
98
99
  }
99
100
  return match[3];
100
101
  }
102
+ /**
103
+ * Creates a session on Vertex AI Agent Engine.
104
+ *
105
+ * @throws if both `ttl` and `expireTime` are specified.
106
+ */
101
107
  async createSession({
102
108
  appName,
103
109
  userId,
104
110
  state,
105
- sessionId
111
+ sessionId,
112
+ ttl,
113
+ expireTime
106
114
  }) {
107
115
  var _a;
116
+ if (ttl != null && expireTime != null) {
117
+ throw new Error(
118
+ "Cannot specify both 'ttl' and 'expireTime' simultaneously."
119
+ );
120
+ }
108
121
  const reasoningEngineId = this.getReasoningEngineId(appName);
109
122
  const filteredState = state ? trimTempState(state) : void 0;
110
123
  let apiResponse = await this.sessions.createInternal({
111
124
  name: "reasoningEngines/".concat(reasoningEngineId),
112
125
  userId,
113
- config: __spreadValues(__spreadValues({}, filteredState ? { sessionState: filteredState } : {}), sessionId ? { sessionId } : {})
126
+ config: __spreadValues(__spreadValues(__spreadValues(__spreadValues({}, filteredState ? { sessionState: filteredState } : {}), sessionId ? { sessionId } : {}), ttl != null ? { ttl } : {}), expireTime != null ? { expireTime } : {})
114
127
  });
115
128
  const operationName = apiResponse.name;
116
129
  let attempts = 0;
@@ -195,7 +208,7 @@ let VertexAiSessionService = class extends BaseSessionService {
195
208
  return session;
196
209
  } catch (error) {
197
210
  const err = error;
198
- if (err.code === GRPC_NOT_FOUND || err.code === HTTP_NOT_FOUND) {
211
+ if (err.code === GRPC_NOT_FOUND || err.code === HTTP_NOT_FOUND || err.status === HTTP_NOT_FOUND) {
199
212
  return void 0;
200
213
  }
201
214
  logger.error("Error getting session from Vertex AI: ".concat(err.message));
@@ -37,6 +37,9 @@ const ALLOWED_FRONTMATTER_KEYS = /* @__PURE__ */ new Set([
37
37
  "description",
38
38
  "license",
39
39
  "allowed-tools",
40
+ // Camel-case alias: FrontmatterSchema's preprocessor derives `allowedTools`
41
+ // from `allowed-tools`, and `.loose()` passes either spelling through.
42
+ "allowedTools",
40
43
  "metadata",
41
44
  "compatibility"
42
45
  ]);
@@ -99,7 +102,7 @@ async function loadDir(directoryPath) {
99
102
  }
100
103
  return files;
101
104
  }
102
- function parseSkillMdContent(content) {
105
+ function parseFrontmatterYaml(content) {
103
106
  if (!content.startsWith("---")) {
104
107
  throw new Error("SKILL.md must start with YAML frontmatter (---)");
105
108
  }
@@ -111,15 +114,34 @@ function parseSkillMdContent(content) {
111
114
  const body = parts.filter((_, i) => i >= 2).join("---").trim();
112
115
  try {
113
116
  const parsed = yaml.load(frontmatterStr);
114
- if (typeof parsed !== "object" || parsed === null) {
117
+ if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
115
118
  throw new Error("SKILL.md frontmatter must be a YAML mapping");
116
119
  }
117
- const frontmatter = FrontmatterSchema.parse(parsed);
118
- return { frontmatter, body };
120
+ return { raw: parsed, body };
119
121
  } catch (e) {
120
122
  throw new Error("Invalid YAML in frontmatter: ".concat(e.message));
121
123
  }
122
124
  }
125
+ function validateFrontmatter(raw) {
126
+ try {
127
+ return FrontmatterSchema.parse(raw);
128
+ } catch (e) {
129
+ throw new Error("Invalid YAML in frontmatter: ".concat(e.message));
130
+ }
131
+ }
132
+ function parseSkillMdContent(content) {
133
+ const { raw, body } = parseFrontmatterYaml(content);
134
+ return { frontmatter: validateFrontmatter(raw), body };
135
+ }
136
+ function isDangerousZipEntryName(entryName) {
137
+ if (path.posix.isAbsolute(entryName) || path.win32.isAbsolute(entryName)) {
138
+ return true;
139
+ }
140
+ return entryName.split(/[/\\]/).some((segment) => segment === "..");
141
+ }
142
+ function isBareSkillName(name) {
143
+ return name !== "." && name !== ".." && path.basename(name) === name;
144
+ }
123
145
  async function loadSkillFromDir(skillDir) {
124
146
  const resolvedDir = path.resolve(skillDir);
125
147
  const skill = await loadSkillFile(skillDir);
@@ -258,6 +280,11 @@ async function loadAllSkillsInDir(skillsBasePath) {
258
280
  function loadSkillFromZipBuffer(zipBuffer) {
259
281
  const zip = new AdmZip(zipBuffer);
260
282
  const entries = zip.getEntries();
283
+ for (const entry of entries) {
284
+ if (isDangerousZipEntryName(entry.entryName)) {
285
+ throw new Error("Dangerous zip entry ignored: ".concat(entry.entryName));
286
+ }
287
+ }
261
288
  let skillMdContent = "";
262
289
  for (const entry of entries) {
263
290
  if (entry.isDirectory) continue;
@@ -269,8 +296,15 @@ function loadSkillFromZipBuffer(zipBuffer) {
269
296
  if (!skillMdContent) {
270
297
  throw new Error("SKILL.md not found in zipped filesystem.");
271
298
  }
272
- const { frontmatter: parsed, body } = parseSkillMdContent(skillMdContent);
273
- const frontmatter = FrontmatterSchema.parse(parsed);
299
+ const { raw, body } = parseFrontmatterYaml(skillMdContent);
300
+ const skillName = raw["name"];
301
+ if (!skillName) {
302
+ throw new Error("SKILL.md frontmatter must contain 'name'");
303
+ }
304
+ if (typeof skillName !== "string" || !isBareSkillName(skillName)) {
305
+ throw new Error("Invalid skill name in SKILL.md: ".concat(String(skillName)));
306
+ }
307
+ const frontmatter = validateFrontmatter(raw);
274
308
  const references = {};
275
309
  const assets = {};
276
310
  const scripts = {};
@@ -0,0 +1,55 @@
1
+ import {createRequire as topLevelCreateRequire} from 'module';
2
+ const require = topLevelCreateRequire(import.meta.url);
3
+ /**
4
+ * @license
5
+ * Copyright 2026 Google LLC
6
+ * SPDX-License-Identifier: Apache-2.0
7
+ */
8
+ import {
9
+ isGemini1Model,
10
+ isGeminiModel,
11
+ isGeminiModelIdCheckDisabled
12
+ } from "../utils/model_name.js";
13
+ import { BaseTool } from "./base_tool.js";
14
+ function applyEnterpriseWebSearch(llmRequest) {
15
+ if (!llmRequest.model) {
16
+ return;
17
+ }
18
+ const modelCheckDisabled = isGeminiModelIdCheckDisabled();
19
+ llmRequest.config = llmRequest.config || {};
20
+ llmRequest.config.tools = llmRequest.config.tools || [];
21
+ if (isGeminiModel(llmRequest.model) || modelCheckDisabled) {
22
+ if (isGemini1Model(llmRequest.model) && llmRequest.config.tools.length > 0) {
23
+ throw new Error(
24
+ "Enterprise Web Search tool cannot be used with other tools in Gemini 1.x."
25
+ );
26
+ }
27
+ llmRequest.config.tools.push({ enterpriseWebSearch: {} });
28
+ return;
29
+ }
30
+ throw new Error(
31
+ "Enterprise Web Search tool is not supported for model ".concat(llmRequest.model)
32
+ );
33
+ }
34
+ class EnterpriseWebSearchTool extends BaseTool {
35
+ constructor() {
36
+ super({
37
+ name: "enterprise_web_search",
38
+ description: "Enterprise Web Search Tool"
39
+ });
40
+ }
41
+ runAsync() {
42
+ return Promise.resolve();
43
+ }
44
+ async processLlmRequest({
45
+ llmRequest
46
+ }) {
47
+ applyEnterpriseWebSearch(llmRequest);
48
+ }
49
+ }
50
+ const ENTERPRISE_WEB_SEARCH = new EnterpriseWebSearchTool();
51
+ export {
52
+ ENTERPRISE_WEB_SEARCH,
53
+ EnterpriseWebSearchTool,
54
+ applyEnterpriseWebSearch
55
+ };
@@ -0,0 +1,42 @@
1
+ import {createRequire as topLevelCreateRequire} from 'module';
2
+ const require = topLevelCreateRequire(import.meta.url);
3
+ /**
4
+ * @license
5
+ * Copyright 2026 Google LLC
6
+ * SPDX-License-Identifier: Apache-2.0
7
+ */
8
+ import { buildExampleSi } from "../examples/example_util.js";
9
+ import { appendInstructions } from "../models/llm_request.js";
10
+ import {
11
+ BaseTool
12
+ } from "./base_tool.js";
13
+ class ExampleTool extends BaseTool {
14
+ constructor(examples) {
15
+ super({
16
+ // Name and description are not used because this tool only changes
17
+ // llmRequest.
18
+ name: "example_tool",
19
+ description: "example tool"
20
+ });
21
+ this.examples = examples;
22
+ }
23
+ async runAsync(_request) {
24
+ throw new Error("ExampleTool should not be called by model");
25
+ }
26
+ async processLlmRequest({
27
+ toolContext,
28
+ llmRequest
29
+ }) {
30
+ var _a, _b;
31
+ const parts = (_a = toolContext.userContent) == null ? void 0 : _a.parts;
32
+ if (!parts || !((_b = parts[0]) == null ? void 0 : _b.text)) {
33
+ return;
34
+ }
35
+ appendInstructions(llmRequest, [
36
+ buildExampleSi(this.examples, parts[0].text, llmRequest.model)
37
+ ]);
38
+ }
39
+ }
40
+ export {
41
+ ExampleTool
42
+ };
@@ -0,0 +1,25 @@
1
+ import {createRequire as topLevelCreateRequire} from 'module';
2
+ const require = topLevelCreateRequire(import.meta.url);
3
+ /**
4
+ * @license
5
+ * Copyright 2026 Google LLC
6
+ * SPDX-License-Identifier: Apache-2.0
7
+ */
8
+ import { z } from "zod";
9
+ import { LongRunningFunctionTool } from "./long_running_tool.js";
10
+ const getUserChoiceTool = new LongRunningFunctionTool({
11
+ name: "get_user_choice",
12
+ description: "Presents a list of options to the user and awaits their selection.",
13
+ parameters: z.object({
14
+ options: z.array(z.string()).describe("List of options to present to the user.")
15
+ }),
16
+ execute: async (input, context) => {
17
+ if (context) {
18
+ context.actions.skipSummarization = true;
19
+ }
20
+ return null;
21
+ }
22
+ });
23
+ export {
24
+ getUserChoiceTool
25
+ };