@google/adk 2.1.0 → 2.2.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 (143) hide show
  1. package/dist/cjs/a2a/agent_card.js +8 -0
  2. package/dist/cjs/a2a/agent_executor.js +8 -3
  3. package/dist/cjs/agents/llm_agent.js +15 -1
  4. package/dist/cjs/agents/processors/content_processor_utils.js +10 -2
  5. package/dist/cjs/agents/processors/nl_planning_processor.js +114 -0
  6. package/dist/cjs/artifacts/gcs_artifact_service.js +13 -7
  7. package/dist/cjs/auth/auth_credential.js +12 -2
  8. package/dist/cjs/code_executors/code_execution_utils.js +3 -3
  9. package/dist/cjs/common.js +45 -0
  10. package/dist/cjs/examples/example.js +92 -0
  11. package/dist/cjs/examples/example_util.js +28 -4
  12. package/dist/cjs/examples/index.js +39 -0
  13. package/dist/cjs/examples/vertex_ai_example_store.js +39 -0
  14. package/dist/cjs/index.js +46 -0
  15. package/dist/cjs/memory/vertex_ai_memory_bank_service.js +17 -5
  16. package/dist/cjs/models/base_llm.js +1 -6
  17. package/dist/cjs/models/chrome_prompt_llm.js +16 -2
  18. package/dist/cjs/models/chrome_prompt_utils.js +54 -2
  19. package/dist/cjs/models/gemini_llm_connection.js +5 -4
  20. package/dist/cjs/planners/base_planner.js +56 -0
  21. package/dist/cjs/planners/built_in_planner.js +85 -0
  22. package/dist/cjs/planners/plan_re_act_planner.js +172 -0
  23. package/dist/cjs/plugins/base_plugin.js +46 -61
  24. package/dist/cjs/tools/example_tool.js +1 -1
  25. package/dist/cjs/tools/mcp/mcp_session_manager.js +14 -8
  26. package/dist/cjs/tools/openapi_tool/auth/auth_helpers.js +281 -2
  27. package/dist/cjs/tools/openapi_tool/auth/credential_exchangers/auto_auth_credential_exchanger.js +15 -1
  28. package/dist/cjs/tools/openapi_tool/auth/credential_exchangers/base_auth_credential_exchanger.js +70 -0
  29. package/dist/cjs/tools/openapi_tool/auth/credential_exchangers/oauth2_exchanger.js +120 -0
  30. package/dist/cjs/tools/openapi_tool/auth/credential_exchangers/service_account_exchanger.js +10 -10
  31. package/dist/cjs/tools/openapi_tool/common/common.js +139 -0
  32. package/dist/cjs/tools/openapi_tool/openapi_spec_parser/openapi_spec_parser.js +11 -6
  33. package/dist/cjs/tools/openapi_tool/openapi_spec_parser/operation_parser.js +73 -13
  34. package/dist/cjs/tools/openapi_tool/openapi_spec_parser/tool_auth_handler.js +146 -34
  35. package/dist/cjs/tools/openapi_tool/openapi_toolset.js +14 -2
  36. package/dist/cjs/tools/openapi_tool/rest_api_tool.js +90 -28
  37. package/dist/cjs/tools/skill/skill_toolset.js +2 -0
  38. package/dist/cjs/tools/tool_context.js +41 -0
  39. package/dist/cjs/tools/webmcp/index.js +37 -0
  40. package/dist/cjs/tools/webmcp/webmcp_tool.js +156 -0
  41. package/dist/cjs/tools/webmcp/webmcp_toolset.js +116 -0
  42. package/dist/cjs/tools/webmcp/webmcp_types.js +50 -0
  43. package/dist/cjs/utils/case_utils.js +52 -2
  44. package/dist/cjs/utils/client_labels.js +67 -0
  45. package/dist/cjs/utils/gemini_schema_util.js +103 -3
  46. package/dist/cjs/utils/hash_utils.js +73 -0
  47. package/dist/cjs/utils/live_connection_utils.js +10 -9
  48. package/dist/cjs/utils/model_name.js +17 -2
  49. package/dist/cjs/utils/simple_zod_to_json.js +5 -0
  50. package/dist/cjs/version.js +1 -1
  51. package/dist/esm/a2a/agent_card.js +8 -0
  52. package/dist/esm/a2a/agent_executor.js +8 -3
  53. package/dist/esm/agents/llm_agent.js +18 -1
  54. package/dist/esm/agents/processors/content_processor_utils.js +10 -2
  55. package/dist/esm/agents/processors/nl_planning_processor.js +87 -0
  56. package/dist/esm/artifacts/gcs_artifact_service.js +13 -7
  57. package/dist/esm/auth/auth_credential.js +11 -1
  58. package/dist/esm/code_executors/code_execution_utils.js +3 -3
  59. package/dist/esm/common.js +38 -2
  60. package/dist/esm/examples/example.js +85 -0
  61. package/dist/esm/examples/example_util.js +25 -3
  62. package/dist/esm/examples/index.js +11 -0
  63. package/dist/esm/examples/vertex_ai_example_store.js +11 -0
  64. package/dist/esm/index.js +51 -1
  65. package/dist/esm/memory/vertex_ai_memory_bank_service.js +17 -5
  66. package/dist/esm/models/base_llm.js +2 -7
  67. package/dist/esm/models/chrome_prompt_llm.js +20 -3
  68. package/dist/esm/models/chrome_prompt_utils.js +51 -2
  69. package/dist/esm/models/gemini_llm_connection.js +6 -5
  70. package/dist/esm/planners/base_planner.js +28 -0
  71. package/dist/esm/planners/built_in_planner.js +57 -0
  72. package/dist/esm/planners/plan_re_act_planner.js +145 -0
  73. package/dist/esm/plugins/base_plugin.js +46 -61
  74. package/dist/esm/tools/example_tool.js +1 -1
  75. package/dist/esm/tools/mcp/mcp_session_manager.js +14 -8
  76. package/dist/esm/tools/openapi_tool/auth/auth_helpers.js +272 -1
  77. package/dist/esm/tools/openapi_tool/auth/credential_exchangers/auto_auth_credential_exchanger.js +15 -1
  78. package/dist/esm/tools/openapi_tool/auth/credential_exchangers/base_auth_credential_exchanger.js +43 -0
  79. package/dist/esm/tools/openapi_tool/auth/credential_exchangers/oauth2_exchanger.js +93 -0
  80. package/dist/esm/tools/openapi_tool/auth/credential_exchangers/service_account_exchanger.js +10 -12
  81. package/dist/esm/tools/openapi_tool/common/common.js +112 -0
  82. package/dist/esm/tools/openapi_tool/openapi_spec_parser/openapi_spec_parser.js +11 -6
  83. package/dist/esm/tools/openapi_tool/openapi_spec_parser/operation_parser.js +80 -13
  84. package/dist/esm/tools/openapi_tool/openapi_spec_parser/tool_auth_handler.js +146 -33
  85. package/dist/esm/tools/openapi_tool/openapi_toolset.js +14 -2
  86. package/dist/esm/tools/openapi_tool/rest_api_tool.js +89 -28
  87. package/dist/esm/tools/skill/skill_toolset.js +2 -0
  88. package/dist/esm/tools/tool_context.js +15 -0
  89. package/dist/esm/tools/webmcp/index.js +10 -0
  90. package/dist/esm/tools/webmcp/webmcp_tool.js +131 -0
  91. package/dist/esm/tools/webmcp/webmcp_toolset.js +89 -0
  92. package/dist/esm/tools/webmcp/webmcp_types.js +22 -0
  93. package/dist/esm/utils/case_utils.js +49 -1
  94. package/dist/esm/utils/client_labels.js +65 -0
  95. package/dist/esm/utils/gemini_schema_util.js +102 -3
  96. package/dist/esm/utils/hash_utils.js +45 -0
  97. package/dist/esm/utils/live_connection_utils.js +11 -10
  98. package/dist/esm/utils/model_name.js +15 -2
  99. package/dist/esm/utils/simple_zod_to_json.js +5 -0
  100. package/dist/esm/version.js +1 -1
  101. package/dist/types/agents/llm_agent.d.ts +12 -1
  102. package/dist/types/agents/processors/nl_planning_processor.d.ts +30 -0
  103. package/dist/types/auth/auth_credential.d.ts +9 -0
  104. package/dist/types/common.d.ts +16 -4
  105. package/dist/types/examples/base_example_provider.d.ts +2 -2
  106. package/dist/types/examples/example.d.ts +75 -0
  107. package/dist/types/examples/example_util.d.ts +13 -2
  108. package/dist/types/examples/index.d.ts +18 -0
  109. package/dist/types/examples/vertex_ai_example_store.d.ts +7 -0
  110. package/dist/types/index.d.ts +12 -3
  111. package/dist/types/memory/memory_entry.d.ts +15 -0
  112. package/dist/types/memory/vertex_ai_memory_bank_service.d.ts +9 -0
  113. package/dist/types/models/chrome_prompt_utils.d.ts +29 -0
  114. package/dist/types/planners/base_planner.d.ts +50 -0
  115. package/dist/types/planners/built_in_planner.d.ts +53 -0
  116. package/dist/types/planners/plan_re_act_planner.d.ts +21 -0
  117. package/dist/types/plugins/base_plugin.d.ts +52 -52
  118. package/dist/types/skills/skill_registry.d.ts +8 -0
  119. package/dist/types/tools/openapi_tool/auth/auth_helpers.d.ts +110 -1
  120. package/dist/types/tools/openapi_tool/auth/credential_exchangers/auto_auth_credential_exchanger.d.ts +32 -2
  121. package/dist/types/tools/openapi_tool/auth/credential_exchangers/base_auth_credential_exchanger.d.ts +35 -0
  122. package/dist/types/tools/openapi_tool/auth/credential_exchangers/oauth2_exchanger.d.ts +54 -0
  123. package/dist/types/tools/openapi_tool/common/common.d.ts +60 -0
  124. package/dist/types/tools/openapi_tool/openapi_spec_parser/openapi_spec_parser.d.ts +7 -0
  125. package/dist/types/tools/openapi_tool/openapi_spec_parser/operation_parser.d.ts +56 -2
  126. package/dist/types/tools/openapi_tool/openapi_spec_parser/tool_auth_handler.d.ts +73 -5
  127. package/dist/types/tools/openapi_tool/openapi_toolset.d.ts +11 -0
  128. package/dist/types/tools/openapi_tool/rest_api_tool.d.ts +42 -8
  129. package/dist/types/tools/tool_context.d.ts +19 -0
  130. package/dist/types/tools/webmcp/index.d.ts +12 -0
  131. package/dist/types/tools/webmcp/webmcp_tool.d.ts +47 -0
  132. package/dist/types/tools/webmcp/webmcp_toolset.d.ts +67 -0
  133. package/dist/types/tools/webmcp/webmcp_types.d.ts +69 -0
  134. package/dist/types/utils/case_utils.d.ts +36 -0
  135. package/dist/types/utils/client_labels.d.ts +33 -0
  136. package/dist/types/utils/gemini_schema_util.d.ts +13 -0
  137. package/dist/types/utils/hash_utils.d.ts +25 -0
  138. package/dist/types/utils/logger.d.ts +10 -2
  139. package/dist/types/utils/model_name.d.ts +30 -2
  140. package/dist/types/version.d.ts +1 -1
  141. package/dist/web/index_web.js +112 -79
  142. package/dist/web/index_web.js.map +4 -4
  143. package/package.json +8 -2
@@ -16,6 +16,7 @@ var __decorateClass = (decorators, target, key, kind) => {
16
16
  * Copyright 2026 Google LLC
17
17
  * SPDX-License-Identifier: Apache-2.0
18
18
  */
19
+ import { toSnakeCaseName } from "../../../utils/case_utils.js";
19
20
  import { experimental } from "../../../utils/experimental.js";
20
21
  import { OperationParser } from "./operation_parser.js";
21
22
  const VALID_SCHEMA_TYPES = /* @__PURE__ */ new Set([
@@ -47,9 +48,13 @@ __decorateClass([
47
48
  OpenApiSpecParser = __decorateClass([
48
49
  experimental
49
50
  ], OpenApiSpecParser);
51
+ function deepCopy(value) {
52
+ return JSON.parse(JSON.stringify(value));
53
+ }
54
+ __name(deepCopy, "deepCopy");
50
55
  function resolveReferences(spec) {
51
56
  const resolvedCache = /* @__PURE__ */ new Map();
52
- const specCopy = JSON.parse(JSON.stringify(spec));
57
+ const specCopy = deepCopy(spec);
53
58
  const recursiveResolve = /* @__PURE__ */ __name((obj, currentDoc, seenRefs = /* @__PURE__ */ new Set()) => {
54
59
  if (typeof obj !== "object" || obj === null) {
55
60
  return obj;
@@ -67,13 +72,13 @@ function resolveReferences(spec) {
67
72
  }
68
73
  seenRefs.add(refString);
69
74
  if (resolvedCache.has(refString)) {
70
- return resolvedCache.get(refString);
75
+ return deepCopy(resolvedCache.get(refString));
71
76
  }
72
77
  let resolvedValue = resolveRef(refString, currentDoc);
73
78
  if (resolvedValue !== void 0) {
74
79
  resolvedValue = recursiveResolve(resolvedValue, currentDoc, seenRefs);
75
80
  resolvedCache.set(refString, resolvedValue);
76
- return resolvedValue;
81
+ return deepCopy(resolvedValue);
77
82
  } else {
78
83
  return obj;
79
84
  }
@@ -104,7 +109,6 @@ function resolveRef(refString, currentDoc) {
104
109
  }
105
110
  __name(resolveRef, "resolveRef");
106
111
  function sanitizeSchemaTypes(openapiSpec) {
107
- const specCopy = JSON.parse(JSON.stringify(openapiSpec));
108
112
  const sanitizeTypeField = /* @__PURE__ */ __name((schemaDict) => {
109
113
  if (!("type" in schemaDict)) return;
110
114
  const typeValue = schemaDict["type"];
@@ -150,7 +154,7 @@ function sanitizeSchemaTypes(openapiSpec) {
150
154
  }
151
155
  return objRecord;
152
156
  }, "sanitizeRecursive");
153
- return sanitizeRecursive(specCopy, false);
157
+ return sanitizeRecursive(openapiSpec, false);
154
158
  }
155
159
  __name(sanitizeSchemaTypes, "sanitizeSchemaTypes");
156
160
  function resolveServerUrl(server) {
@@ -198,7 +202,7 @@ function collectOperations(spec, options = {}) {
198
202
  const opParams = operation.parameters || [];
199
203
  operation.parameters = [...opParams, ...pathParams];
200
204
  if (!operation.operationId) {
201
- operation.operationId = `${method}_${path.replace(/[^a-zA-Z0-9]/g, "_")}`;
205
+ operation.operationId = toSnakeCaseName(`${path}_${method}`);
202
206
  }
203
207
  const parser = new OperationParser(operation, {
204
208
  preservePropertyNames
@@ -215,6 +219,7 @@ function collectOperations(spec, options = {}) {
215
219
  endpoint: { baseUrl, path, method },
216
220
  operation,
217
221
  parameters: parser.getParameters(),
222
+ returnValue: parser.getReturnValue(),
218
223
  authScheme
219
224
  });
220
225
  }
@@ -16,23 +16,48 @@ var __decorateClass = (decorators, target, key, kind) => {
16
16
  * Copyright 2026 Google LLC
17
17
  * SPDX-License-Identifier: Apache-2.0
18
18
  */
19
+ import {
20
+ renameReservedKeywords,
21
+ toSnakeCaseName
22
+ } from "../../../utils/case_utils.js";
19
23
  import { experimental } from "../../../utils/experimental.js";
24
+ import {
25
+ generateParamDoc,
26
+ generateReturnDoc,
27
+ getTypeHint
28
+ } from "../common/common.js";
20
29
  let OperationParser = class {
30
+ /**
31
+ * @param operation The operation to parse. A string is parsed as JSON, and a
32
+ * plain object is used as given.
33
+ * @param options.preservePropertyNames Keeps the original parameter and
34
+ * function names instead of converting them to snake_case.
35
+ * @param options.shouldParse Whether to parse the operation during
36
+ * construction. Defaults to `true`.
37
+ */
21
38
  constructor(operation, options = {}) {
22
- this.operation = operation;
23
39
  this.params = [];
24
- var _a;
40
+ var _a, _b;
41
+ this.operation = typeof operation === "string" ? JSON.parse(operation) : operation;
25
42
  this.preservePropertyNames = (_a = options.preservePropertyNames) != null ? _a : false;
26
- this.processOperationParameters();
27
- this.processRequestBody();
28
- this.processReturnValue();
29
- this.dedupeParamNames();
43
+ if ((_b = options.shouldParse) != null ? _b : true) {
44
+ this.processOperationParameters();
45
+ this.processRequestBody();
46
+ this.returnValue = this.processReturnValue();
47
+ this.dedupeParamNames();
48
+ }
49
+ }
50
+ static load(operation, params, returnValue) {
51
+ const parser = new this(operation, { shouldParse: false });
52
+ parser.params = params;
53
+ parser.returnValue = returnValue;
54
+ return parser;
30
55
  }
31
56
  getParamName(originalName) {
32
57
  if (this.preservePropertyNames) {
33
58
  return originalName;
34
59
  }
35
- return originalName.replace(/[A-Z]/g, (g) => "_" + g.toLowerCase()).replace(/^_/, "");
60
+ return renameReservedKeywords(toSnakeCaseName(originalName));
36
61
  }
37
62
  processOperationParameters() {
38
63
  const parameters = this.operation.parameters || [];
@@ -54,6 +79,7 @@ let OperationParser = class {
54
79
  }
55
80
  }
56
81
  processRequestBody() {
82
+ var _a;
57
83
  const requestBody = this.operation.requestBody;
58
84
  if (!requestBody || "$ref" in requestBody) {
59
85
  return;
@@ -64,9 +90,9 @@ let OperationParser = class {
64
90
  return;
65
91
  }
66
92
  const mediaTypeObject = content[firstMimeType];
67
- const schema = mediaTypeObject.schema;
93
+ const schema = (_a = mediaTypeObject.schema) != null ? _a : {};
68
94
  const description = requestBody.description || "";
69
- if (schema && !("$ref" in schema)) {
95
+ if (!("$ref" in schema)) {
70
96
  if (schema.type === "object") {
71
97
  const properties = schema.properties || {};
72
98
  if (Object.keys(properties).length > 0) {
@@ -121,16 +147,16 @@ let OperationParser = class {
121
147
  if (min20x) {
122
148
  const response = responses[min20x];
123
149
  if (!("$ref" in response) && response.content) {
124
- const firstMimeType = Object.keys(response.content)[0];
125
- if (firstMimeType) {
126
- const schema = response.content[firstMimeType].schema;
150
+ for (const mediaType of Object.values(response.content)) {
151
+ const schema = mediaType.schema;
127
152
  if (schema && !("$ref" in schema)) {
128
153
  returnSchema = schema;
154
+ break;
129
155
  }
130
156
  }
131
157
  }
132
158
  }
133
- this.returnValue = {
159
+ return {
134
160
  originalName: "",
135
161
  paramLocation: "",
136
162
  paramSchema: returnSchema,
@@ -178,6 +204,32 @@ let OperationParser = class {
178
204
  getDescription() {
179
205
  return this.operation.description || this.operation.summary || "";
180
206
  }
207
+ getAuthSchemeName() {
208
+ var _a, _b;
209
+ const security = (_a = this.operation.security) != null ? _a : [];
210
+ return security.length > 0 ? (_b = Object.keys(security[0])[0]) != null ? _b : "" : "";
211
+ }
212
+ getReturnValue() {
213
+ return this.returnValue;
214
+ }
215
+ getReturnTypeHint() {
216
+ var _a;
217
+ return getTypeHint((_a = this.returnValue) == null ? void 0 : _a.paramSchema);
218
+ }
219
+ getPydocString() {
220
+ var _a;
221
+ const description = this.operation.summary || this.operation.description || "";
222
+ const argLines = this.params.map((param) => ` ${generateParamDoc(param)}`).join("\n");
223
+ const returnDoc = generateReturnDoc((_a = this.operation.responses) != null ? _a : {});
224
+ const returnBlock = returnDoc ? `
225
+
226
+ ${returnDoc}` : "";
227
+ return `"""${description}
228
+
229
+ Args:
230
+ ${argLines}${returnBlock}
231
+ """`;
232
+ }
181
233
  };
182
234
  __name(OperationParser, "OperationParser");
183
235
  __decorateClass([
@@ -192,6 +244,21 @@ __decorateClass([
192
244
  __decorateClass([
193
245
  experimental
194
246
  ], OperationParser.prototype, "getDescription", 1);
247
+ __decorateClass([
248
+ experimental
249
+ ], OperationParser.prototype, "getAuthSchemeName", 1);
250
+ __decorateClass([
251
+ experimental
252
+ ], OperationParser.prototype, "getReturnValue", 1);
253
+ __decorateClass([
254
+ experimental
255
+ ], OperationParser.prototype, "getReturnTypeHint", 1);
256
+ __decorateClass([
257
+ experimental
258
+ ], OperationParser.prototype, "getPydocString", 1);
259
+ __decorateClass([
260
+ experimental
261
+ ], OperationParser, "load", 1);
195
262
  OperationParser = __decorateClass([
196
263
  experimental
197
264
  ], OperationParser);
@@ -16,71 +16,183 @@ var __decorateClass = (decorators, target, key, kind) => {
16
16
  * Copyright 2026 Google LLC
17
17
  * SPDX-License-Identifier: Apache-2.0
18
18
  */
19
+ import { cloneDeep } from "lodash-es";
20
+ import {
21
+ isAuthCredential
22
+ } from "../../../auth/auth_credential.js";
19
23
  import { experimental } from "../../../utils/experimental.js";
24
+ import { stableHash } from "../../../utils/hash_utils.js";
25
+ import { logger } from "../../../utils/logger.js";
20
26
  import { AutoAuthCredentialExchanger } from "../auth/credential_exchangers/auto_auth_credential_exchanger.js";
27
+ import { AuthCredentialMissingError } from "../auth/credential_exchangers/base_auth_credential_exchanger.js";
28
+ const DEFAULT_CREDENTIAL_KEY = "default_openapi_key";
21
29
  const _ToolContextCredentialStore = class _ToolContextCredentialStore {
22
30
  constructor(context) {
23
31
  this.context = context;
24
32
  }
25
- getCredentialKey(authScheme) {
26
- const schemeName = (authScheme == null ? void 0 : authScheme.type) || "default";
27
- return `${schemeName}_existing_exchanged_credential`;
33
+ /**
34
+ * Returns the state key that holds the credential exchanged for this scheme
35
+ * and credential pair.
36
+ *
37
+ * Both operands are hashed into the key, so two tools configured with
38
+ * different schemes, or with different credentials under one scheme, never
39
+ * share a slot.
40
+ *
41
+ * The key deliberately carries no `temp:` prefix. Session state is a copy and
42
+ * only the delta is persisted, and `temp:` is cleared at the end of a run,
43
+ * while an exchanged token has to stay readable across runs.
44
+ */
45
+ getCredentialKey(authScheme, authCredential) {
46
+ const schemeName = authScheme ? `${authScheme.type}_${stableHash(authScheme)}` : "";
47
+ const credentialName = authCredential ? `${authCredential.authType}_${stableHash(authCredential)}` : "";
48
+ return `${schemeName}_${credentialName}_existing_exchanged_credential`;
28
49
  }
29
- getCredential(authScheme) {
30
- const key = this.getCredentialKey(authScheme);
31
- return this.context.state.get(key);
50
+ /**
51
+ * Returns the credential stored for this scheme and credential pair, or
52
+ * `undefined` when there is none.
53
+ *
54
+ * @throws Error if the state entry under the key is not an
55
+ * {@link AuthCredential}, which means something else wrote to the key.
56
+ */
57
+ getCredential(authScheme, authCredential) {
58
+ const key = this.getCredentialKey(authScheme, authCredential);
59
+ const stored = this.context.state.get(key);
60
+ if (stored === void 0 || stored === null) {
61
+ return void 0;
62
+ }
63
+ if (!isAuthCredential(stored)) {
64
+ throw new Error(
65
+ `State entry '${key}' is not an AuthCredential. Another writer has taken this key.`
66
+ );
67
+ }
68
+ return stored;
32
69
  }
33
70
  storeCredential(key, credential) {
34
- this.context.state.set(key, credential);
71
+ this.context.state.set(key, JSON.parse(JSON.stringify(credential)));
72
+ }
73
+ /**
74
+ * Makes the credential under `key` unreadable again.
75
+ *
76
+ * adk-python deletes the state entry. `State` has no delete, so this writes
77
+ * `undefined`, which `State.get` returns for a missing key as well, and
78
+ * {@link getCredential} therefore misses exactly as a delete would make it.
79
+ */
80
+ removeCredential(key) {
81
+ this.context.state.set(key, void 0);
35
82
  }
36
83
  };
37
84
  __name(_ToolContextCredentialStore, "ToolContextCredentialStore");
38
85
  let ToolContextCredentialStore = _ToolContextCredentialStore;
39
86
  let ToolAuthHandler = class {
40
- constructor(context, authScheme, authCredential, credentialKey) {
87
+ constructor(context, authScheme, authCredential, options = {}) {
41
88
  this.context = context;
42
- this.authScheme = authScheme;
43
- this.authCredential = authCredential;
44
- this.credentialKey = credentialKey;
89
+ var _a;
90
+ this.authScheme = authScheme ? cloneDeep(authScheme) : void 0;
91
+ this.authCredential = authCredential ? cloneDeep(authCredential) : void 0;
92
+ this.credentialKey = options.credentialKey;
93
+ this.credentialExchanger = options.credentialExchanger;
94
+ this.credentialStore = (_a = options.credentialStore) != null ? _a : new ToolContextCredentialStore(context);
45
95
  }
46
96
  static fromToolContext(context, authScheme, authCredential, options = {}) {
47
- return new ToolAuthHandler(
48
- context,
49
- authScheme,
50
- authCredential,
51
- options.credentialKey
52
- );
97
+ return new ToolAuthHandler(context, authScheme, authCredential, options);
53
98
  }
54
99
  async prepareAuthCredentials() {
55
100
  if (!this.authScheme) {
56
101
  return { state: "done" };
57
102
  }
58
- const store = new ToolContextCredentialStore(this.context);
59
- const existingCredential = store.getCredential(this.authScheme);
103
+ const existingCredential = this.credentialStore.getCredential(
104
+ this.authScheme,
105
+ this.authCredential
106
+ );
60
107
  if (existingCredential) {
61
- return { state: "done", authCredential: existingCredential };
108
+ return {
109
+ state: "done",
110
+ authScheme: this.authScheme,
111
+ authCredential: existingCredential
112
+ };
62
113
  }
63
114
  const authConfig = {
64
115
  authScheme: this.authScheme,
65
116
  rawAuthCredential: this.authCredential,
66
- credentialKey: this.credentialKey || "default_openapi_key"
117
+ credentialKey: this.credentialKey || DEFAULT_CREDENTIAL_KEY
67
118
  };
68
119
  const authResponseCredential = this.context.getAuthResponse(authConfig);
69
120
  const credential = authResponseCredential != null ? authResponseCredential : this.authCredential;
70
- if (!credential) {
71
- this.context.requestCredential(authConfig);
72
- return { state: "pending" };
121
+ const exchanged = credential ? await this.tryExchange(credential) : void 0;
122
+ if (!exchanged) {
123
+ this.requestCredential(authConfig);
124
+ return {
125
+ state: "pending",
126
+ authScheme: this.authScheme,
127
+ authCredential: this.authCredential
128
+ };
73
129
  }
74
- const exchanger = new AutoAuthCredentialExchanger();
75
- const result = await exchanger.exchange({
130
+ if (authResponseCredential || exchanged.wasExchanged) {
131
+ const key = this.credentialStore.getCredentialKey(
132
+ this.authScheme,
133
+ this.authCredential
134
+ );
135
+ this.credentialStore.storeCredential(key, exchanged.credential);
136
+ }
137
+ return {
138
+ state: "done",
76
139
  authScheme: this.authScheme,
77
- authCredential: credential
78
- });
79
- if (authResponseCredential || result.wasExchanged) {
80
- const key = store.getCredentialKey(this.authScheme);
81
- store.storeCredential(key, result.credential);
140
+ authCredential: exchanged.credential
141
+ };
142
+ }
143
+ /**
144
+ * Exchanges `credential`, or returns `undefined` when the exchange failed.
145
+ *
146
+ * An exchange failure is transient far more often than it is fatal, so it
147
+ * becomes a `pending` result the client can resume from rather than an
148
+ * exception that fails the whole tool call.
149
+ */
150
+ async tryExchange(credential) {
151
+ var _a;
152
+ const exchanger = (_a = this.credentialExchanger) != null ? _a : new AutoAuthCredentialExchanger();
153
+ try {
154
+ return await exchanger.exchange({
155
+ authScheme: this.authScheme,
156
+ authCredential: credential
157
+ });
158
+ } catch (e) {
159
+ logger.error(
160
+ `Failed to exchange credential: ${e instanceof Error ? e.message : e}`
161
+ );
162
+ return void 0;
163
+ }
164
+ }
165
+ /**
166
+ * Asks the client for a credential, after checking that an interactive
167
+ * scheme has the OAuth2 client configuration it cannot proceed without.
168
+ *
169
+ * @throws Error if an `oauth2` or `openIdConnect` scheme has no OAuth2
170
+ * credential.
171
+ * @throws AuthCredentialMissingError if that credential omits `clientId` or
172
+ * `clientSecret`.
173
+ */
174
+ requestCredential(authConfig) {
175
+ var _a, _b;
176
+ const schemeType = (_a = this.authScheme) == null ? void 0 : _a.type;
177
+ if (schemeType === "oauth2" || schemeType === "openIdConnect") {
178
+ const oauth2 = (_b = this.authCredential) == null ? void 0 : _b.oauth2;
179
+ if (!oauth2) {
180
+ throw new Error(
181
+ `authCredential is empty for scheme ${schemeType}. Please create AuthCredential using OAuth2Auth.`
182
+ );
183
+ }
184
+ if (!oauth2.clientId) {
185
+ throw new AuthCredentialMissingError(
186
+ "OAuth2 credentials clientId is missing."
187
+ );
188
+ }
189
+ if (!oauth2.clientSecret) {
190
+ throw new AuthCredentialMissingError(
191
+ "OAuth2 credentials clientSecret is missing."
192
+ );
193
+ }
82
194
  }
83
- return { state: "done", authCredential: result.credential };
195
+ this.context.requestCredential(authConfig);
84
196
  }
85
197
  };
86
198
  __name(ToolAuthHandler, "ToolAuthHandler");
@@ -94,5 +206,6 @@ ToolAuthHandler = __decorateClass([
94
206
  experimental
95
207
  ], ToolAuthHandler);
96
208
  export {
97
- ToolAuthHandler
209
+ ToolAuthHandler,
210
+ ToolContextCredentialStore
98
211
  };
@@ -18,6 +18,7 @@ var __decorateClass = (decorators, target, key, kind) => {
18
18
  */
19
19
  import yaml from "js-yaml";
20
20
  import { experimental } from "../../utils/experimental.js";
21
+ import { logger } from "../../utils/logger.js";
21
22
  import { BaseToolset } from "../base_toolset.js";
22
23
  import { OpenApiSpecParser } from "./openapi_spec_parser/openapi_spec_parser.js";
23
24
  import { createRestApiTool } from "./rest_api_tool.js";
@@ -29,8 +30,10 @@ let OpenAPIToolset = class extends BaseToolset {
29
30
  if (!spec && options.specStr) {
30
31
  if (options.specType === "yaml" || !options.specType && options.specStr.trim().startsWith("---")) {
31
32
  spec = yaml.load(options.specStr);
32
- } else {
33
+ } else if (options.specType === "json" || !options.specType) {
33
34
  spec = JSON.parse(options.specStr);
35
+ } else {
36
+ throw new Error(`Unsupported spec type: ${options.specType}`);
34
37
  }
35
38
  }
36
39
  if (!spec) {
@@ -51,7 +54,9 @@ let OpenAPIToolset = class extends BaseToolset {
51
54
  description: op.description,
52
55
  endpoint: op.endpoint,
53
56
  operation: op.operation,
54
- authScheme: op.authScheme
57
+ authScheme: op.authScheme,
58
+ parameters: op.parameters,
59
+ authCredential: op.authCredential
55
60
  },
56
61
  {
57
62
  preservePropertyNames: options.preservePropertyNames,
@@ -60,6 +65,7 @@ let OpenAPIToolset = class extends BaseToolset {
60
65
  }
61
66
  );
62
67
  this.tools.push(tool);
68
+ logger.info(`Parsed tool: ${tool.name}`);
63
69
  }
64
70
  if (options.authScheme || options.authCredential) {
65
71
  for (const tool of this.tools) {
@@ -80,6 +86,9 @@ let OpenAPIToolset = class extends BaseToolset {
80
86
  return true;
81
87
  });
82
88
  }
89
+ getTool(toolName) {
90
+ return this.tools.find((tool) => tool.name === toolName);
91
+ }
83
92
  async close() {
84
93
  return Promise.resolve();
85
94
  }
@@ -88,6 +97,9 @@ __name(OpenAPIToolset, "OpenAPIToolset");
88
97
  __decorateClass([
89
98
  experimental
90
99
  ], OpenAPIToolset.prototype, "getTools", 1);
100
+ __decorateClass([
101
+ experimental
102
+ ], OpenAPIToolset.prototype, "getTool", 1);
91
103
  __decorateClass([
92
104
  experimental
93
105
  ], OpenAPIToolset.prototype, "close", 1);