@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.
- package/dist/cjs/a2a/a2a_remote_agent.js +12 -2
- package/dist/cjs/a2a/agent_to_a2a.js +18 -3
- package/dist/cjs/a2a/auth.js +65 -0
- package/dist/cjs/a2a/event_converter_utils.js +47 -18
- package/dist/cjs/a2a/metadata_converter_utils.js +1 -1
- package/dist/cjs/agents/base_agent.js +39 -0
- package/dist/cjs/agents/functions.js +26 -28
- package/dist/cjs/agents/llm_agent.js +4 -2
- package/dist/cjs/agents/loop_agent.js +15 -3
- package/dist/cjs/agents/processors/basic_llm_request_processor.js +3 -2
- package/dist/cjs/agents/processors/content_processor_utils.js +2 -1
- package/dist/cjs/agents/processors/content_request_processor.js +2 -21
- package/dist/cjs/agents/processors/instructions_llm_request_processor.js +3 -1
- package/dist/cjs/agents/routed_agent.js +31 -0
- package/dist/cjs/agents/run_config.js +3 -2
- package/dist/cjs/artifacts/in_memory_artifact_service.js +17 -9
- package/dist/cjs/auth/credential_service/in_memory_credential_service.js +14 -3
- package/dist/cjs/code_executors/unsafe_local_code_executor.js +23 -12
- package/dist/cjs/common.js +35 -0
- package/dist/cjs/context/agent_controlled_context_compactor.js +2 -11
- package/dist/cjs/context/anchored_context_compactor.js +127 -0
- package/dist/cjs/context/compaction_utils.js +64 -0
- package/dist/cjs/context/token_based_context_compactor.js +13 -44
- package/dist/cjs/events/compacted_event.js +9 -3
- package/dist/cjs/events/event.js +28 -0
- package/dist/cjs/index.js +7 -0
- package/dist/cjs/integrations/agent_registry/agent_registry_mcp_toolset.js +9 -1
- package/dist/cjs/memory/in_memory_memory_service.js +13 -2
- package/dist/cjs/memory/vertex_ai_memory_bank_service.js +3 -0
- package/dist/cjs/plugins/base_plugin.js +4 -2
- package/dist/cjs/plugins/global_instruction_plugin.js +97 -0
- package/dist/cjs/runner/runner.js +69 -23
- package/dist/cjs/sessions/base_session_service.js +8 -3
- package/dist/cjs/sessions/in_memory_session_service.js +8 -8
- package/dist/cjs/sessions/vertex_ai_session_service.js +22 -10
- package/dist/cjs/skills/loader.js +40 -6
- package/dist/cjs/tools/enterprise_web_search_tool.js +81 -0
- package/dist/cjs/tools/example_tool.js +68 -0
- package/dist/cjs/tools/get_user_choice_tool.js +53 -0
- package/dist/cjs/tools/load_web_page.js +250 -0
- package/dist/cjs/tools/mcp/load_mcp_resource_tool.js +140 -0
- package/dist/cjs/tools/mcp/mcp_session_manager.js +35 -21
- package/dist/cjs/tools/mcp/mcp_toolset.js +63 -0
- package/dist/cjs/tools/openapi_tool/openapi_spec_parser/tool_auth_handler.js +13 -10
- package/dist/cjs/tools/request_input_tool.js +54 -0
- package/dist/cjs/tools/skill/run_skill_inline_script_tool.js +54 -4
- package/dist/cjs/tools/skill/skill_toolset.js +4 -2
- package/dist/cjs/utils/branch_trie.js +41 -0
- package/dist/cjs/utils/crypto_shim.js +43 -0
- package/dist/cjs/utils/env_aware_utils.js +15 -13
- package/dist/cjs/utils/error_utils.js +120 -0
- package/dist/cjs/utils/file_utils.js +5 -2
- package/dist/cjs/utils/output_schema_utils.js +43 -0
- package/dist/cjs/utils/streaming_utils.js +5 -5
- package/dist/cjs/utils/vertex_ai_utils.js +3 -0
- package/dist/cjs/version.js +1 -1
- package/dist/esm/a2a/a2a_remote_agent.js +12 -2
- package/dist/esm/a2a/agent_to_a2a.js +18 -3
- package/dist/esm/a2a/auth.js +37 -0
- package/dist/esm/a2a/event_converter_utils.js +47 -18
- package/dist/esm/a2a/metadata_converter_utils.js +1 -1
- package/dist/esm/agents/base_agent.js +39 -0
- package/dist/esm/agents/functions.js +27 -24
- package/dist/esm/agents/llm_agent.js +6 -4
- package/dist/esm/agents/loop_agent.js +15 -3
- package/dist/esm/agents/processors/basic_llm_request_processor.js +3 -2
- package/dist/esm/agents/processors/content_processor_utils.js +2 -1
- package/dist/esm/agents/processors/content_request_processor.js +2 -21
- package/dist/esm/agents/processors/instructions_llm_request_processor.js +3 -1
- package/dist/esm/agents/routed_agent.js +31 -0
- package/dist/esm/agents/run_config.js +3 -2
- package/dist/esm/artifacts/in_memory_artifact_service.js +17 -9
- package/dist/esm/auth/credential_service/in_memory_credential_service.js +14 -3
- package/dist/esm/code_executors/unsafe_local_code_executor.js +22 -11
- package/dist/esm/common.js +29 -1
- package/dist/esm/context/agent_controlled_context_compactor.js +2 -11
- package/dist/esm/context/anchored_context_compactor.js +99 -0
- package/dist/esm/context/compaction_utils.js +38 -0
- package/dist/esm/context/token_based_context_compactor.js +16 -44
- package/dist/esm/events/compacted_event.js +7 -2
- package/dist/esm/events/event.js +24 -0
- package/dist/esm/index.js +8 -1
- package/dist/esm/integrations/agent_registry/agent_registry_mcp_toolset.js +9 -1
- package/dist/esm/memory/in_memory_memory_service.js +13 -2
- package/dist/esm/memory/vertex_ai_memory_bank_service.js +7 -1
- package/dist/esm/plugins/base_plugin.js +4 -2
- package/dist/esm/plugins/global_instruction_plugin.js +69 -0
- package/dist/esm/runner/runner.js +69 -23
- package/dist/esm/sessions/base_session_service.js +8 -3
- package/dist/esm/sessions/in_memory_session_service.js +8 -8
- package/dist/esm/sessions/vertex_ai_session_service.js +26 -11
- package/dist/esm/skills/loader.js +40 -6
- package/dist/esm/tools/enterprise_web_search_tool.js +55 -0
- package/dist/esm/tools/example_tool.js +42 -0
- package/dist/esm/tools/get_user_choice_tool.js +25 -0
- package/dist/esm/tools/load_web_page.js +221 -0
- package/dist/esm/tools/mcp/load_mcp_resource_tool.js +114 -0
- package/dist/esm/tools/mcp/mcp_session_manager.js +35 -21
- package/dist/esm/tools/mcp/mcp_toolset.js +63 -0
- package/dist/esm/tools/openapi_tool/openapi_spec_parser/tool_auth_handler.js +13 -10
- package/dist/esm/tools/request_input_tool.js +26 -0
- package/dist/esm/tools/skill/run_skill_inline_script_tool.js +53 -4
- package/dist/esm/tools/skill/skill_toolset.js +4 -2
- package/dist/esm/utils/branch_trie.js +13 -0
- package/dist/esm/utils/crypto_shim.js +15 -0
- package/dist/esm/utils/env_aware_utils.js +15 -13
- package/dist/esm/utils/error_utils.js +92 -0
- package/dist/esm/utils/file_utils.js +5 -2
- package/dist/esm/utils/output_schema_utils.js +15 -0
- package/dist/esm/utils/streaming_utils.js +1 -1
- package/dist/esm/utils/vertex_ai_utils.js +2 -0
- package/dist/esm/version.js +1 -1
- package/dist/types/a2a/a2a_remote_agent.d.ts +5 -1
- package/dist/types/a2a/agent_to_a2a.d.ts +38 -0
- package/dist/types/a2a/auth.d.ts +30 -0
- package/dist/types/a2a/event_converter_utils.d.ts +4 -1
- package/dist/types/agents/base_agent.d.ts +29 -1
- package/dist/types/agents/functions.d.ts +1 -9
- package/dist/types/agents/llm_agent.d.ts +5 -1
- package/dist/types/agents/loop_agent.d.ts +2 -2
- package/dist/types/agents/routed_agent.d.ts +24 -1
- package/dist/types/agents/run_config.d.ts +1 -1
- package/dist/types/auth/credential_service/in_memory_credential_service.d.ts +11 -0
- package/dist/types/code_executors/unsafe_local_code_executor.d.ts +5 -1
- package/dist/types/common.d.ts +11 -2
- package/dist/types/context/agent_controlled_context_compactor.d.ts +0 -1
- package/dist/types/context/anchored_context_compactor.d.ts +35 -0
- package/dist/types/context/compaction_utils.d.ts +23 -0
- package/dist/types/context/token_based_context_compactor.d.ts +0 -1
- package/dist/types/events/compacted_event.d.ts +10 -0
- package/dist/types/events/event.d.ts +13 -0
- package/dist/types/index.d.ts +5 -3
- package/dist/types/memory/in_memory_memory_service.d.ts +11 -0
- package/dist/types/plugins/base_plugin.d.ts +4 -2
- package/dist/types/plugins/global_instruction_plugin.d.ts +38 -0
- package/dist/types/runner/runner.d.ts +1 -1
- package/dist/types/sessions/base_session_service.d.ts +8 -0
- package/dist/types/sessions/in_memory_session_service.d.ts +9 -0
- package/dist/types/sessions/vertex_ai_session_service.d.ts +19 -1
- package/dist/types/skills/loader.d.ts +5 -0
- package/dist/types/tools/enterprise_web_search_tool.d.ts +26 -0
- package/dist/types/tools/example_tool.d.ts +21 -0
- package/dist/types/tools/get_user_choice_tool.d.ts +14 -0
- package/dist/types/tools/load_web_page.d.ts +33 -0
- package/dist/types/tools/mcp/load_mcp_resource_tool.d.ts +26 -0
- package/dist/types/tools/mcp/mcp_toolset.d.ts +27 -0
- package/dist/types/tools/request_input_tool.d.ts +15 -0
- package/dist/types/tools/skill/run_skill_inline_script_tool.d.ts +25 -0
- package/dist/types/tools/skill/skill_toolset.d.ts +9 -0
- package/dist/types/utils/branch_trie.d.ts +14 -0
- package/dist/types/utils/crypto_shim.d.ts +16 -0
- package/dist/types/utils/env_aware_utils.d.ts +23 -0
- package/dist/types/utils/error_utils.d.ts +18 -0
- package/dist/types/utils/output_schema_utils.d.ts +18 -0
- package/dist/types/utils/vertex_ai_utils.d.ts +1 -0
- package/dist/types/version.d.ts +1 -1
- package/dist/web/a2a/a2a_remote_agent.js +12 -2
- package/dist/web/a2a/agent_to_a2a.js +18 -3
- package/dist/web/a2a/auth.js +37 -0
- package/dist/web/a2a/event_converter_utils.js +47 -18
- package/dist/web/a2a/metadata_converter_utils.js +1 -1
- package/dist/web/agents/base_agent.js +39 -0
- package/dist/web/agents/functions.js +27 -24
- package/dist/web/agents/llm_agent.js +6 -4
- package/dist/web/agents/loop_agent.js +27 -3
- package/dist/web/agents/processors/basic_llm_request_processor.js +3 -2
- package/dist/web/agents/processors/content_processor_utils.js +2 -1
- package/dist/web/agents/processors/content_request_processor.js +2 -21
- package/dist/web/agents/processors/instructions_llm_request_processor.js +3 -1
- package/dist/web/agents/routed_agent.js +31 -0
- package/dist/web/agents/run_config.js +8 -3
- package/dist/web/artifacts/in_memory_artifact_service.js +17 -9
- package/dist/web/auth/credential_service/in_memory_credential_service.js +14 -3
- package/dist/web/code_executors/unsafe_local_code_executor.js +22 -11
- package/dist/web/common.js +29 -1
- package/dist/web/context/agent_controlled_context_compactor.js +2 -11
- package/dist/web/context/anchored_context_compactor.js +117 -0
- package/dist/web/context/compaction_utils.js +38 -0
- package/dist/web/context/token_based_context_compactor.js +16 -44
- package/dist/web/events/compacted_event.js +7 -2
- package/dist/web/events/event.js +24 -0
- package/dist/web/index.js +8 -1
- package/dist/web/integrations/agent_registry/agent_registry_mcp_toolset.js +9 -1
- package/dist/web/memory/in_memory_memory_service.js +13 -2
- package/dist/web/memory/vertex_ai_memory_bank_service.js +7 -1
- package/dist/web/plugins/base_plugin.js +4 -2
- package/dist/web/plugins/global_instruction_plugin.js +67 -0
- package/dist/web/runner/runner.js +65 -22
- package/dist/web/sessions/base_session_service.js +8 -3
- package/dist/web/sessions/in_memory_session_service.js +8 -8
- package/dist/web/sessions/vertex_ai_session_service.js +24 -11
- package/dist/web/skills/loader.js +40 -6
- package/dist/web/tools/enterprise_web_search_tool.js +55 -0
- package/dist/web/tools/example_tool.js +42 -0
- package/dist/web/tools/get_user_choice_tool.js +25 -0
- package/dist/web/tools/load_web_page.js +221 -0
- package/dist/web/tools/mcp/load_mcp_resource_tool.js +107 -0
- package/dist/web/tools/mcp/mcp_session_manager.js +35 -21
- package/dist/web/tools/mcp/mcp_toolset.js +63 -0
- package/dist/web/tools/openapi_tool/openapi_spec_parser/tool_auth_handler.js +13 -10
- package/dist/web/tools/request_input_tool.js +26 -0
- package/dist/web/tools/skill/run_skill_inline_script_tool.js +51 -4
- package/dist/web/tools/skill/skill_toolset.js +4 -2
- package/dist/web/utils/branch_trie.js +13 -0
- package/dist/web/utils/crypto_shim.js +15 -0
- package/dist/web/utils/env_aware_utils.js +15 -13
- package/dist/web/utils/error_utils.js +92 -0
- package/dist/web/utils/file_utils.js +5 -2
- package/dist/web/utils/output_schema_utils.js +15 -0
- package/dist/web/utils/streaming_utils.js +1 -1
- package/dist/web/utils/vertex_ai_utils.js +2 -0
- package/dist/web/version.js +1 -1
- package/package.json +1 -1
|
@@ -61,7 +61,12 @@ class BaseSessionService {
|
|
|
61
61
|
if (key.startsWith(State.TEMP_PREFIX)) {
|
|
62
62
|
continue;
|
|
63
63
|
}
|
|
64
|
-
session.state
|
|
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
|
}
|
|
@@ -19,7 +19,10 @@ import { Client } from "@google-cloud/vertexai/build/src/genai/client.js";
|
|
|
19
19
|
import { isCompactedEvent } from "../events/compacted_event.js";
|
|
20
20
|
import { experimental } from "../utils/experimental.js";
|
|
21
21
|
import { logger } from "../utils/logger.js";
|
|
22
|
-
import {
|
|
22
|
+
import {
|
|
23
|
+
EXPRESS_MODE_UNSUPPORTED_MESSAGE,
|
|
24
|
+
getExpressModeApiKey
|
|
25
|
+
} from "../utils/vertex_ai_utils.js";
|
|
23
26
|
import { partialCopy } from "../utils/partial_copy.js";
|
|
24
27
|
import {
|
|
25
28
|
BaseSessionService,
|
|
@@ -47,16 +50,14 @@ let VertexAiSessionService = class extends BaseSessionService {
|
|
|
47
50
|
this.location,
|
|
48
51
|
options.expressModeApiKey
|
|
49
52
|
);
|
|
50
|
-
if (!options.sessions) {
|
|
51
|
-
if (!this.expressModeApiKey && (!this.projectId || !this.location)) {
|
|
52
|
-
throw new Error(
|
|
53
|
-
"Either (Project ID and Location) or an expressModeApiKey is required."
|
|
54
|
-
);
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
53
|
if (options.sessions) {
|
|
58
54
|
this.sessions = options.sessions;
|
|
59
55
|
} else {
|
|
56
|
+
if (!this.projectId || !this.location) {
|
|
57
|
+
throw new Error(
|
|
58
|
+
this.expressModeApiKey ? EXPRESS_MODE_UNSUPPORTED_MESSAGE : "Project ID and Location are required."
|
|
59
|
+
);
|
|
60
|
+
}
|
|
60
61
|
const client = new Client({
|
|
61
62
|
project: this.projectId,
|
|
62
63
|
location: this.location
|
|
@@ -80,13 +81,25 @@ let VertexAiSessionService = class extends BaseSessionService {
|
|
|
80
81
|
}
|
|
81
82
|
return match[3];
|
|
82
83
|
}
|
|
84
|
+
/**
|
|
85
|
+
* Creates a session on Vertex AI Agent Engine.
|
|
86
|
+
*
|
|
87
|
+
* @throws if both `ttl` and `expireTime` are specified.
|
|
88
|
+
*/
|
|
83
89
|
async createSession({
|
|
84
90
|
appName,
|
|
85
91
|
userId,
|
|
86
92
|
state,
|
|
87
|
-
sessionId
|
|
93
|
+
sessionId,
|
|
94
|
+
ttl,
|
|
95
|
+
expireTime
|
|
88
96
|
}) {
|
|
89
97
|
var _a;
|
|
98
|
+
if (ttl != null && expireTime != null) {
|
|
99
|
+
throw new Error(
|
|
100
|
+
"Cannot specify both 'ttl' and 'expireTime' simultaneously."
|
|
101
|
+
);
|
|
102
|
+
}
|
|
90
103
|
const reasoningEngineId = this.getReasoningEngineId(appName);
|
|
91
104
|
const filteredState = state ? trimTempState(state) : void 0;
|
|
92
105
|
let apiResponse = await this.sessions.createInternal({
|
|
@@ -94,7 +107,9 @@ let VertexAiSessionService = class extends BaseSessionService {
|
|
|
94
107
|
userId,
|
|
95
108
|
config: {
|
|
96
109
|
...filteredState ? { sessionState: filteredState } : {},
|
|
97
|
-
...sessionId ? { sessionId } : {}
|
|
110
|
+
...sessionId ? { sessionId } : {},
|
|
111
|
+
...ttl != null ? { ttl } : {},
|
|
112
|
+
...expireTime != null ? { expireTime } : {}
|
|
98
113
|
}
|
|
99
114
|
});
|
|
100
115
|
const operationName = apiResponse.name;
|
|
@@ -180,7 +195,7 @@ let VertexAiSessionService = class extends BaseSessionService {
|
|
|
180
195
|
return session;
|
|
181
196
|
} catch (error) {
|
|
182
197
|
const err = error;
|
|
183
|
-
if (err.code === GRPC_NOT_FOUND || err.code === HTTP_NOT_FOUND) {
|
|
198
|
+
if (err.code === GRPC_NOT_FOUND || err.code === HTTP_NOT_FOUND || err.status === HTTP_NOT_FOUND) {
|
|
184
199
|
return void 0;
|
|
185
200
|
}
|
|
186
201
|
logger.error(`Error getting session from Vertex AI: ${err.message}`);
|
|
@@ -18,6 +18,9 @@ const ALLOWED_FRONTMATTER_KEYS = /* @__PURE__ */ new Set([
|
|
|
18
18
|
"description",
|
|
19
19
|
"license",
|
|
20
20
|
"allowed-tools",
|
|
21
|
+
// Camel-case alias: FrontmatterSchema's preprocessor derives `allowedTools`
|
|
22
|
+
// from `allowed-tools`, and `.loose()` passes either spelling through.
|
|
23
|
+
"allowedTools",
|
|
21
24
|
"metadata",
|
|
22
25
|
"compatibility"
|
|
23
26
|
]);
|
|
@@ -80,7 +83,7 @@ async function loadDir(directoryPath) {
|
|
|
80
83
|
}
|
|
81
84
|
return files;
|
|
82
85
|
}
|
|
83
|
-
function
|
|
86
|
+
function parseFrontmatterYaml(content) {
|
|
84
87
|
if (!content.startsWith("---")) {
|
|
85
88
|
throw new Error("SKILL.md must start with YAML frontmatter (---)");
|
|
86
89
|
}
|
|
@@ -92,15 +95,34 @@ function parseSkillMdContent(content) {
|
|
|
92
95
|
const body = parts.filter((_, i) => i >= 2).join("---").trim();
|
|
93
96
|
try {
|
|
94
97
|
const parsed = yaml.load(frontmatterStr);
|
|
95
|
-
if (typeof parsed !== "object" || parsed === null) {
|
|
98
|
+
if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
|
|
96
99
|
throw new Error("SKILL.md frontmatter must be a YAML mapping");
|
|
97
100
|
}
|
|
98
|
-
|
|
99
|
-
return { frontmatter, body };
|
|
101
|
+
return { raw: parsed, body };
|
|
100
102
|
} catch (e) {
|
|
101
103
|
throw new Error(`Invalid YAML in frontmatter: ${e.message}`);
|
|
102
104
|
}
|
|
103
105
|
}
|
|
106
|
+
function validateFrontmatter(raw) {
|
|
107
|
+
try {
|
|
108
|
+
return FrontmatterSchema.parse(raw);
|
|
109
|
+
} catch (e) {
|
|
110
|
+
throw new Error(`Invalid YAML in frontmatter: ${e.message}`);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
function parseSkillMdContent(content) {
|
|
114
|
+
const { raw, body } = parseFrontmatterYaml(content);
|
|
115
|
+
return { frontmatter: validateFrontmatter(raw), body };
|
|
116
|
+
}
|
|
117
|
+
function isDangerousZipEntryName(entryName) {
|
|
118
|
+
if (path.posix.isAbsolute(entryName) || path.win32.isAbsolute(entryName)) {
|
|
119
|
+
return true;
|
|
120
|
+
}
|
|
121
|
+
return entryName.split(/[/\\]/).some((segment) => segment === "..");
|
|
122
|
+
}
|
|
123
|
+
function isBareSkillName(name) {
|
|
124
|
+
return name !== "." && name !== ".." && path.basename(name) === name;
|
|
125
|
+
}
|
|
104
126
|
async function loadSkillFromDir(skillDir) {
|
|
105
127
|
const resolvedDir = path.resolve(skillDir);
|
|
106
128
|
const skill = await loadSkillFile(skillDir);
|
|
@@ -240,6 +262,11 @@ async function loadAllSkillsInDir(skillsBasePath) {
|
|
|
240
262
|
function loadSkillFromZipBuffer(zipBuffer) {
|
|
241
263
|
const zip = new AdmZip(zipBuffer);
|
|
242
264
|
const entries = zip.getEntries();
|
|
265
|
+
for (const entry of entries) {
|
|
266
|
+
if (isDangerousZipEntryName(entry.entryName)) {
|
|
267
|
+
throw new Error(`Dangerous zip entry ignored: ${entry.entryName}`);
|
|
268
|
+
}
|
|
269
|
+
}
|
|
243
270
|
let skillMdContent = "";
|
|
244
271
|
for (const entry of entries) {
|
|
245
272
|
if (entry.isDirectory) continue;
|
|
@@ -251,8 +278,15 @@ function loadSkillFromZipBuffer(zipBuffer) {
|
|
|
251
278
|
if (!skillMdContent) {
|
|
252
279
|
throw new Error("SKILL.md not found in zipped filesystem.");
|
|
253
280
|
}
|
|
254
|
-
const {
|
|
255
|
-
const
|
|
281
|
+
const { raw, body } = parseFrontmatterYaml(skillMdContent);
|
|
282
|
+
const skillName = raw["name"];
|
|
283
|
+
if (!skillName) {
|
|
284
|
+
throw new Error("SKILL.md frontmatter must contain 'name'");
|
|
285
|
+
}
|
|
286
|
+
if (typeof skillName !== "string" || !isBareSkillName(skillName)) {
|
|
287
|
+
throw new Error(`Invalid skill name in SKILL.md: ${String(skillName)}`);
|
|
288
|
+
}
|
|
289
|
+
const frontmatter = validateFrontmatter(raw);
|
|
256
290
|
const references = {};
|
|
257
291
|
const assets = {};
|
|
258
292
|
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 ${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
|
+
};
|
|
@@ -0,0 +1,221 @@
|
|
|
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 { lookup } from "node:dns/promises";
|
|
9
|
+
import { isIP } from "node:net";
|
|
10
|
+
import { z } from "zod";
|
|
11
|
+
import { FunctionTool } from "./function_tool.js";
|
|
12
|
+
const ALLOWED_SCHEMES = /* @__PURE__ */ new Set(["http:", "https:"]);
|
|
13
|
+
const DEFAULT_TIMEOUT_MS = 3e4;
|
|
14
|
+
const BLOCKED_IPV4_CIDRS = [
|
|
15
|
+
"0.0.0.0/8",
|
|
16
|
+
// "this host on this network"
|
|
17
|
+
"10.0.0.0/8",
|
|
18
|
+
// private
|
|
19
|
+
"100.64.0.0/10",
|
|
20
|
+
// shared address space / CGNAT
|
|
21
|
+
"127.0.0.0/8",
|
|
22
|
+
// loopback
|
|
23
|
+
"169.254.0.0/16",
|
|
24
|
+
// link-local (includes GCP metadata 169.254.169.254)
|
|
25
|
+
"172.16.0.0/12",
|
|
26
|
+
// private
|
|
27
|
+
"192.0.0.0/24",
|
|
28
|
+
// IETF protocol assignments
|
|
29
|
+
"192.0.2.0/24",
|
|
30
|
+
// TEST-NET-1 (documentation)
|
|
31
|
+
"192.88.99.0/24",
|
|
32
|
+
// 6to4 relay anycast (deprecated)
|
|
33
|
+
"192.168.0.0/16",
|
|
34
|
+
// private
|
|
35
|
+
"198.18.0.0/15",
|
|
36
|
+
// benchmarking
|
|
37
|
+
"198.51.100.0/24",
|
|
38
|
+
// TEST-NET-2 (documentation)
|
|
39
|
+
"203.0.113.0/24",
|
|
40
|
+
// TEST-NET-3 (documentation)
|
|
41
|
+
"224.0.0.0/4",
|
|
42
|
+
// multicast
|
|
43
|
+
"240.0.0.0/4"
|
|
44
|
+
// reserved / future use (includes 255.255.255.255)
|
|
45
|
+
].map(parseIpv4Cidr);
|
|
46
|
+
const BLOCKED_IPV6_CIDRS = [
|
|
47
|
+
"::/128",
|
|
48
|
+
// unspecified
|
|
49
|
+
"::1/128",
|
|
50
|
+
// loopback
|
|
51
|
+
"64:ff9b:1::/48",
|
|
52
|
+
// local NAT64
|
|
53
|
+
"100::/64",
|
|
54
|
+
// discard-only
|
|
55
|
+
"2001:db8::/32",
|
|
56
|
+
// documentation
|
|
57
|
+
"fc00::/7",
|
|
58
|
+
// unique-local (ULA, private)
|
|
59
|
+
"fe80::/10",
|
|
60
|
+
// link-local
|
|
61
|
+
"ff00::/8"
|
|
62
|
+
// multicast
|
|
63
|
+
].map(parseIpv6Cidr);
|
|
64
|
+
function failedToFetchMessage(url) {
|
|
65
|
+
return `Failed to fetch url: ${url}`;
|
|
66
|
+
}
|
|
67
|
+
function isBlockedHostname(hostname) {
|
|
68
|
+
const normalized = hostname.replace(/\.+$/, "").toLowerCase();
|
|
69
|
+
return normalized === "localhost" || normalized.endsWith(".localhost");
|
|
70
|
+
}
|
|
71
|
+
function normalizeHost(hostname) {
|
|
72
|
+
return hostname.startsWith("[") ? hostname.slice(1, -1) : hostname;
|
|
73
|
+
}
|
|
74
|
+
function parseIpv4(address) {
|
|
75
|
+
const match = /^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/.exec(address);
|
|
76
|
+
if (!match) {
|
|
77
|
+
return null;
|
|
78
|
+
}
|
|
79
|
+
const octets = match.slice(1).map(Number);
|
|
80
|
+
if (octets.some((octet) => octet > 255)) {
|
|
81
|
+
return null;
|
|
82
|
+
}
|
|
83
|
+
return octets;
|
|
84
|
+
}
|
|
85
|
+
function parseIpv6(address) {
|
|
86
|
+
if (isIP(address) !== 6) {
|
|
87
|
+
return null;
|
|
88
|
+
}
|
|
89
|
+
const [head, tail] = address.split("::");
|
|
90
|
+
const highGroups = head ? expandHextets(head) : [];
|
|
91
|
+
const lowGroups = tail ? expandHextets(tail) : [];
|
|
92
|
+
const compressed = address.includes("::") ? new Array(8 - highGroups.length - lowGroups.length).fill(0) : [];
|
|
93
|
+
return [...highGroups, ...compressed, ...lowGroups];
|
|
94
|
+
}
|
|
95
|
+
function expandHextets(fragment) {
|
|
96
|
+
const hextets = [];
|
|
97
|
+
for (const group of fragment.split(":")) {
|
|
98
|
+
if (group.includes(".")) {
|
|
99
|
+
const octets = parseIpv4(group);
|
|
100
|
+
hextets.push(octets[0] << 8 | octets[1], octets[2] << 8 | octets[3]);
|
|
101
|
+
} else {
|
|
102
|
+
hextets.push(parseInt(group, 16));
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
return hextets;
|
|
106
|
+
}
|
|
107
|
+
function ipv4ToInt(octets) {
|
|
108
|
+
return (octets[0] << 24 | octets[1] << 16 | octets[2] << 8 | octets[3]) >>> 0;
|
|
109
|
+
}
|
|
110
|
+
function hextetsToBigInt(hextets) {
|
|
111
|
+
let value = 0n;
|
|
112
|
+
for (const hextet of hextets) {
|
|
113
|
+
value = value << 16n | BigInt(hextet);
|
|
114
|
+
}
|
|
115
|
+
return value;
|
|
116
|
+
}
|
|
117
|
+
function parseIpv4Cidr(cidr) {
|
|
118
|
+
const [address, prefix] = cidr.split("/");
|
|
119
|
+
const mask = 4294967295 << 32 - Number(prefix) >>> 0;
|
|
120
|
+
return { base: (ipv4ToInt(parseIpv4(address)) & mask) >>> 0, mask };
|
|
121
|
+
}
|
|
122
|
+
function parseIpv6Cidr(cidr) {
|
|
123
|
+
const [address, prefix] = cidr.split("/");
|
|
124
|
+
return { base: hextetsToBigInt(parseIpv6(address)), prefix: Number(prefix) };
|
|
125
|
+
}
|
|
126
|
+
function isBlockedIpv4(octets) {
|
|
127
|
+
const value = ipv4ToInt(octets);
|
|
128
|
+
return BLOCKED_IPV4_CIDRS.some(
|
|
129
|
+
({ base, mask }) => (value & mask) >>> 0 === base
|
|
130
|
+
);
|
|
131
|
+
}
|
|
132
|
+
function isBlockedIpv6(hextets) {
|
|
133
|
+
const value = hextetsToBigInt(hextets);
|
|
134
|
+
if (value >> 32n === 0xffffn) {
|
|
135
|
+
return isBlockedIpv4([
|
|
136
|
+
Number(value >> 24n & 0xffn),
|
|
137
|
+
Number(value >> 16n & 0xffn),
|
|
138
|
+
Number(value >> 8n & 0xffn),
|
|
139
|
+
Number(value & 0xffn)
|
|
140
|
+
]);
|
|
141
|
+
}
|
|
142
|
+
return BLOCKED_IPV6_CIDRS.some(
|
|
143
|
+
({ base, prefix }) => value >> BigInt(128 - prefix) === base >> BigInt(128 - prefix)
|
|
144
|
+
);
|
|
145
|
+
}
|
|
146
|
+
function isBlockedAddress(address) {
|
|
147
|
+
const octets = parseIpv4(address);
|
|
148
|
+
if (octets) {
|
|
149
|
+
return isBlockedIpv4(octets);
|
|
150
|
+
}
|
|
151
|
+
const hextets = parseIpv6(address);
|
|
152
|
+
if (hextets) {
|
|
153
|
+
return isBlockedIpv6(hextets);
|
|
154
|
+
}
|
|
155
|
+
return true;
|
|
156
|
+
}
|
|
157
|
+
async function resolveHostAddresses(hostname) {
|
|
158
|
+
if (isIP(hostname) !== 0) {
|
|
159
|
+
return [hostname];
|
|
160
|
+
}
|
|
161
|
+
const records = await lookup(hostname, { all: true });
|
|
162
|
+
const addresses = [...new Set(records.map((record) => record.address))];
|
|
163
|
+
if (addresses.length === 0) {
|
|
164
|
+
throw new Error(`Unable to resolve host: ${hostname}`);
|
|
165
|
+
}
|
|
166
|
+
return addresses;
|
|
167
|
+
}
|
|
168
|
+
function assertUrlAllowed(url) {
|
|
169
|
+
const parsed = new URL(url);
|
|
170
|
+
if (!ALLOWED_SCHEMES.has(parsed.protocol)) {
|
|
171
|
+
throw new Error(`Unsupported url scheme: ${url}`);
|
|
172
|
+
}
|
|
173
|
+
if (isBlockedHostname(parsed.hostname)) {
|
|
174
|
+
throw new Error(`Blocked host: ${parsed.hostname}`);
|
|
175
|
+
}
|
|
176
|
+
return parsed;
|
|
177
|
+
}
|
|
178
|
+
async function validateResolvedAddresses(hostname) {
|
|
179
|
+
const addresses = await resolveHostAddresses(hostname);
|
|
180
|
+
if (addresses.some(isBlockedAddress)) {
|
|
181
|
+
throw new Error(`Blocked host: ${hostname}`);
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
function decodeHtmlEntities(text) {
|
|
185
|
+
return text.replace(/ /g, " ").replace(/'/g, "'").replace(/'/g, "'").replace(/"/g, '"').replace(/</g, "<").replace(/>/g, ">").replace(/&/g, "&");
|
|
186
|
+
}
|
|
187
|
+
function htmlToText(html) {
|
|
188
|
+
const withoutCode = html.replace(/<script[\s\S]*?<\/script>/gi, " ").replace(/<style[\s\S]*?<\/style>/gi, " ").replace(/<!--[\s\S]*?-->/g, " ");
|
|
189
|
+
const text = decodeHtmlEntities(withoutCode.replace(/<[^>]+>/g, "\n"));
|
|
190
|
+
return text.split("\n").map((line) => line.trim()).filter((line) => line.split(/\s+/).filter(Boolean).length > 3).join("\n");
|
|
191
|
+
}
|
|
192
|
+
async function loadWebPage(url, options) {
|
|
193
|
+
var _a;
|
|
194
|
+
const timeoutMs = (_a = options == null ? void 0 : options.timeoutMs) != null ? _a : DEFAULT_TIMEOUT_MS;
|
|
195
|
+
try {
|
|
196
|
+
const parsed = assertUrlAllowed(url);
|
|
197
|
+
await validateResolvedAddresses(normalizeHost(parsed.hostname));
|
|
198
|
+
const response = await fetch(url, {
|
|
199
|
+
redirect: "manual",
|
|
200
|
+
signal: AbortSignal.timeout(timeoutMs)
|
|
201
|
+
});
|
|
202
|
+
if (response.status !== 200) {
|
|
203
|
+
return failedToFetchMessage(url);
|
|
204
|
+
}
|
|
205
|
+
return htmlToText(await response.text());
|
|
206
|
+
} catch {
|
|
207
|
+
return failedToFetchMessage(url);
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
const LOAD_WEB_PAGE = new FunctionTool({
|
|
211
|
+
name: "load_web_page",
|
|
212
|
+
description: "Fetches the content at the given URL and returns the readable text extracted from the page.",
|
|
213
|
+
parameters: z.object({
|
|
214
|
+
url: z.string().describe("The URL to fetch and extract text from.")
|
|
215
|
+
}),
|
|
216
|
+
execute: ({ url }) => loadWebPage(url)
|
|
217
|
+
});
|
|
218
|
+
export {
|
|
219
|
+
LOAD_WEB_PAGE,
|
|
220
|
+
loadWebPage
|
|
221
|
+
};
|