@iqai/adk 0.8.0 → 0.8.5

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/index.js CHANGED
@@ -1604,12 +1604,21 @@ var InvocationContext = class _InvocationContext {
1604
1604
  * The current session of this invocation context. Readonly.
1605
1605
  */
1606
1606
  session;
1607
+ /**
1608
+ * Shared flags container so that child/parent contexts stay in sync.
1609
+ */
1610
+ _invocationFlags;
1607
1611
  /**
1608
1612
  * Whether to end this invocation.
1609
1613
  *
1610
1614
  * Set to True in callbacks or tools to terminate this invocation.
1611
1615
  */
1612
- endInvocation = false;
1616
+ get endInvocation() {
1617
+ return this._invocationFlags.endInvocation;
1618
+ }
1619
+ set endInvocation(value) {
1620
+ this._invocationFlags.endInvocation = value;
1621
+ }
1613
1622
  /**
1614
1623
  * The queue to receive live requests.
1615
1624
  */
@@ -1650,7 +1659,9 @@ var InvocationContext = class _InvocationContext {
1650
1659
  this.agent = options.agent;
1651
1660
  this.userContent = options.userContent;
1652
1661
  this.session = options.session;
1653
- this.endInvocation = options.endInvocation || false;
1662
+ this._invocationFlags = options.invocationFlags ?? {
1663
+ endInvocation: options.endInvocation || false
1664
+ };
1654
1665
  this.liveRequestQueue = options.liveRequestQueue;
1655
1666
  this.activeStreamingTools = options.activeStreamingTools;
1656
1667
  this.transcriptionCache = options.transcriptionCache;
@@ -1709,6 +1720,12 @@ var InvocationContext = class _InvocationContext {
1709
1720
  getSpanCounters() {
1710
1721
  return this._spanCounters;
1711
1722
  }
1723
+ /**
1724
+ * Exposes shared invocation flags for child contexts.
1725
+ */
1726
+ getInvocationFlags() {
1727
+ return this._invocationFlags;
1728
+ }
1712
1729
  /**
1713
1730
  * Creates a child invocation context for a sub-agent
1714
1731
  */
@@ -1727,7 +1744,7 @@ var InvocationContext = class _InvocationContext {
1727
1744
  // Update to the new agent
1728
1745
  userContent: this.userContent,
1729
1746
  session: this.session,
1730
- endInvocation: this.endInvocation,
1747
+ invocationFlags: this._invocationFlags,
1731
1748
  liveRequestQueue: this.liveRequestQueue,
1732
1749
  activeStreamingTools: this.activeStreamingTools,
1733
1750
  transcriptionCache: this.transcriptionCache,
@@ -3943,15 +3960,10 @@ var VectorStorageProvider = class {
3943
3960
  this.memoryCache.delete(id);
3944
3961
  }
3945
3962
  } else {
3946
- const idsToDelete = [];
3963
+ const vectorFilter = this.buildDeleteFilter(filter);
3964
+ deleted = await this.vectorStore.delete({ filter: vectorFilter });
3947
3965
  for (const [id, record] of this.memoryCache.entries()) {
3948
3966
  if (this.matchesFilter(record, filter)) {
3949
- idsToDelete.push(id);
3950
- }
3951
- }
3952
- if (idsToDelete.length > 0) {
3953
- deleted = await this.vectorStore.delete({ ids: idsToDelete });
3954
- for (const id of idsToDelete) {
3955
3967
  this.memoryCache.delete(id);
3956
3968
  }
3957
3969
  }
@@ -3962,6 +3974,10 @@ var VectorStorageProvider = class {
3962
3974
  * Count memories matching filter.
3963
3975
  */
3964
3976
  async count(filter) {
3977
+ if (this.vectorStore.count) {
3978
+ const vectorFilter = this.buildDeleteFilter(filter);
3979
+ return this.vectorStore.count(vectorFilter);
3980
+ }
3965
3981
  let count = 0;
3966
3982
  for (const record of this.memoryCache.values()) {
3967
3983
  if (this.matchesFilter(record, filter)) {
@@ -4093,15 +4109,34 @@ var VectorStorageProvider = class {
4093
4109
  }
4094
4110
  return filter;
4095
4111
  }
4112
+ /**
4113
+ * Build filter object for vector store delete/count operations.
4114
+ */
4115
+ buildDeleteFilter(filter) {
4116
+ const vectorFilter = {};
4117
+ if (filter.userId !== void 0) vectorFilter.userId = filter.userId;
4118
+ if (filter.appName !== void 0) vectorFilter.appName = filter.appName;
4119
+ if (filter.sessionId !== void 0)
4120
+ vectorFilter.sessionId = filter.sessionId;
4121
+ if (filter.before !== void 0) vectorFilter.before = filter.before;
4122
+ if (filter.after !== void 0) vectorFilter.after = filter.after;
4123
+ if (this.namespace) vectorFilter.namespace = this.namespace;
4124
+ return vectorFilter;
4125
+ }
4096
4126
  /**
4097
4127
  * Check if a record matches the given filter.
4098
4128
  */
4099
4129
  matchesFilter(record, filter) {
4100
- if (filter.userId && record.userId !== filter.userId) return false;
4101
- if (filter.appName && record.appName !== filter.appName) return false;
4102
- if (filter.sessionId && record.sessionId !== filter.sessionId) return false;
4103
- if (filter.before && record.timestamp > filter.before) return false;
4104
- if (filter.after && record.timestamp < filter.after) return false;
4130
+ if (filter.userId !== void 0 && record.userId !== filter.userId)
4131
+ return false;
4132
+ if (filter.appName !== void 0 && record.appName !== filter.appName)
4133
+ return false;
4134
+ if (filter.sessionId !== void 0 && record.sessionId !== filter.sessionId)
4135
+ return false;
4136
+ if (filter.before !== void 0 && record.timestamp > filter.before)
4137
+ return false;
4138
+ if (filter.after !== void 0 && record.timestamp < filter.after)
4139
+ return false;
4105
4140
  return true;
4106
4141
  }
4107
4142
  /**
@@ -4308,11 +4343,12 @@ var LlmSummaryProvider = class {
4308
4343
  }
4309
4344
  const baseUrl = this.baseUrl ?? "https://generativelanguage.googleapis.com/v1beta";
4310
4345
  const response = await fetch(
4311
- `${baseUrl}/models/${this.model}:generateContent?key=${apiKey}`,
4346
+ `${baseUrl}/models/${this.model}:generateContent`,
4312
4347
  {
4313
4348
  method: "POST",
4314
4349
  headers: {
4315
- "Content-Type": "application/json"
4350
+ "Content-Type": "application/json",
4351
+ "x-goog-api-key": apiKey
4316
4352
  },
4317
4353
  body: JSON.stringify({
4318
4354
  contents: [{ parts: [{ text: prompt }] }],
@@ -4689,7 +4725,7 @@ var OPERATIONS = {
4689
4725
  EXECUTE_TOOL: "execute_tool",
4690
4726
  // ============================================
4691
4727
  // ADK-specific operations (framework extensions)
4692
- // These are non-standard but useful for the ADK framework
4728
+ // These are non-standard but useful for the ADK-TS framework
4693
4729
  // ============================================
4694
4730
  TRANSFER_AGENT: "transfer_agent",
4695
4731
  // Multi-agent transfer
@@ -5784,7 +5820,7 @@ var TracingService = class {
5784
5820
  [ADK_ATTRS.INVOCATION_ID]: invocationContext.invocationId,
5785
5821
  [ADK_ATTRS.EVENT_ID]: eventId,
5786
5822
  [ADK_ATTRS.ENVIRONMENT]: getEnvironment() || "",
5787
- // Content attributes (only if capture is enabled) - ADK namespace for backward compat
5823
+ // Content attributes (only if capture is enabled) - ADK-TS namespace for backward compat
5788
5824
  [ADK_ATTRS.LLM_REQUEST]: captureContent ? safeJsonStringify(llmRequestData) : "{}",
5789
5825
  [ADK_ATTRS.LLM_RESPONSE]: captureContent ? safeJsonStringify(llmResponseData) : "{}"
5790
5826
  });
@@ -6483,7 +6519,7 @@ var BaseLlm = class {
6483
6519
  true
6484
6520
  // retry may be recommended for transient model errors
6485
6521
  );
6486
- this.logger.error("\u274C ADK LLM Error:", {
6522
+ this.logger.error("\u274C ADK-TS LLM Error:", {
6487
6523
  model: this.model,
6488
6524
  error: error.message
6489
6525
  });
@@ -7251,7 +7287,7 @@ var AiSdkLlm = class _AiSdkLlm extends BaseLlm {
7251
7287
  });
7252
7288
  }
7253
7289
  /**
7254
- * Convert ADK LlmRequest to AI SDK CoreMessage format
7290
+ * Convert ADK-TS LlmRequest to AI SDK CoreMessage format
7255
7291
  */
7256
7292
  convertToAiSdkMessages(llmRequest) {
7257
7293
  const messages = [];
@@ -7301,7 +7337,7 @@ var AiSdkLlm = class _AiSdkLlm extends BaseLlm {
7301
7337
  return transformedSchema;
7302
7338
  }
7303
7339
  /**
7304
- * Convert ADK tools to AI SDK tools format
7340
+ * Convert ADK-TS tools to AI SDK tools format
7305
7341
  */
7306
7342
  convertToAiSdkTools(llmRequest) {
7307
7343
  const tools = {};
@@ -7322,7 +7358,7 @@ var AiSdkLlm = class _AiSdkLlm extends BaseLlm {
7322
7358
  return tools;
7323
7359
  }
7324
7360
  /**
7325
- * Convert ADK Content to AI SDK CoreMessage
7361
+ * Convert ADK-TS Content to AI SDK CoreMessage
7326
7362
  */
7327
7363
  contentToAiSdkMessage(content) {
7328
7364
  const role = this.mapRole(content.role);
@@ -7424,7 +7460,7 @@ var AiSdkLlm = class _AiSdkLlm extends BaseLlm {
7424
7460
  return { role: "user", content: contentParts };
7425
7461
  }
7426
7462
  /**
7427
- * Map ADK role to AI SDK role
7463
+ * Map ADK-TS role to AI SDK role
7428
7464
  */
7429
7465
  mapRole(role) {
7430
7466
  switch (role) {
@@ -7438,7 +7474,7 @@ var AiSdkLlm = class _AiSdkLlm extends BaseLlm {
7438
7474
  }
7439
7475
  }
7440
7476
  /**
7441
- * Map AI SDK finish reason to ADK finish reason
7477
+ * Map AI SDK finish reason to ADK-TS finish reason
7442
7478
  */
7443
7479
  mapFinishReason(finishReason) {
7444
7480
  switch (finishReason) {
@@ -7457,6 +7493,21 @@ var AiSdkLlm = class _AiSdkLlm extends BaseLlm {
7457
7493
  // src/models/anthropic-llm.ts
7458
7494
  init_logger();
7459
7495
  var import_sdk = __toESM(require("@anthropic-ai/sdk"));
7496
+
7497
+ // src/models/llm-utils.ts
7498
+ function safeParseToolArgs(json, logger2) {
7499
+ try {
7500
+ return JSON.parse(json || "{}");
7501
+ } catch (error) {
7502
+ logger2.warn("Failed to parse tool call arguments, using empty args", {
7503
+ rawArgs: json,
7504
+ error: String(error)
7505
+ });
7506
+ return {};
7507
+ }
7508
+ }
7509
+
7510
+ // src/models/anthropic-llm.ts
7460
7511
  var DEFAULT_MAX_OUTPUT_TOKENS = 1024;
7461
7512
  var THOUGHT_OPEN_TAGS = [
7462
7513
  "<thinking>",
@@ -7662,7 +7713,7 @@ var AnthropicLlm = class extends BaseLlm {
7662
7713
  functionCall: {
7663
7714
  id: block.id,
7664
7715
  name: block.name,
7665
- args: JSON.parse(block.inputJson || "{}")
7716
+ args: safeParseToolArgs(block.inputJson, this.logger)
7666
7717
  }
7667
7718
  });
7668
7719
  }
@@ -7714,7 +7765,7 @@ var AnthropicLlm = class extends BaseLlm {
7714
7765
  throw new Error(`Live connection is not supported for ${this.model}.`);
7715
7766
  }
7716
7767
  /**
7717
- * Convert Anthropic Message to ADK LlmResponse
7768
+ * Convert Anthropic Message to ADK-TS LlmResponse
7718
7769
  */
7719
7770
  anthropicMessageToLlmResponse(message) {
7720
7771
  this.logger.debug(
@@ -7742,7 +7793,7 @@ var AnthropicLlm = class extends BaseLlm {
7742
7793
  });
7743
7794
  }
7744
7795
  /**
7745
- * Convert ADK Content to Anthropic MessageParam
7796
+ * Convert ADK-TS Content to Anthropic MessageParam
7746
7797
  */
7747
7798
  contentToAnthropicMessage(content) {
7748
7799
  return {
@@ -7753,39 +7804,39 @@ var AnthropicLlm = class extends BaseLlm {
7753
7804
  };
7754
7805
  }
7755
7806
  /**
7756
- * Convert ADK Part to Anthropic content block
7807
+ * Convert ADK-TS Part to Anthropic content block
7757
7808
  */
7758
7809
  partToAnthropicBlock(part) {
7759
7810
  if (part.text) return { type: "text", text: part.text };
7760
- if (part.function_call)
7811
+ if (part.functionCall)
7761
7812
  return {
7762
7813
  type: "tool_use",
7763
- id: part.function_call.id || "",
7764
- name: part.function_call.name,
7765
- input: part.function_call.args || {}
7814
+ id: part.functionCall.id || "",
7815
+ name: part.functionCall.name,
7816
+ input: part.functionCall.args || {}
7766
7817
  };
7767
- if (part.function_response)
7818
+ if (part.functionResponse)
7768
7819
  return {
7769
7820
  type: "tool_result",
7770
- tool_use_id: part.function_response.id || "",
7771
- content: String(part.function_response.response?.result || ""),
7821
+ tool_use_id: part.functionResponse.id || "",
7822
+ content: String(part.functionResponse.response?.result || ""),
7772
7823
  is_error: false
7773
7824
  };
7774
7825
  throw new Error("Unsupported part type for Anthropic conversion");
7775
7826
  }
7776
7827
  /**
7777
- * Convert Anthropic content block to ADK Part
7828
+ * Convert Anthropic content block to ADK-TS Part
7778
7829
  */
7779
7830
  anthropicBlockToPart(block) {
7780
7831
  if (block.type === "text") return { text: block.text };
7781
7832
  if (block.type === "tool_use")
7782
7833
  return {
7783
- function_call: { id: block.id, name: block.name, args: block.input }
7834
+ functionCall: { id: block.id, name: block.name, args: block.input }
7784
7835
  };
7785
7836
  throw new Error("Unsupported Anthropic content block type");
7786
7837
  }
7787
7838
  /**
7788
- * Convert ADK function declaration to Anthropic tool param
7839
+ * Convert ADK-TS function declaration to Anthropic tool param
7789
7840
  */
7790
7841
  functionDeclarationToAnthropicTool(functionDeclaration) {
7791
7842
  const properties = {};
@@ -7805,14 +7856,14 @@ var AnthropicLlm = class extends BaseLlm {
7805
7856
  };
7806
7857
  }
7807
7858
  /**
7808
- * Convert ADK role to Anthropic role format
7859
+ * Convert ADK-TS role to Anthropic role format
7809
7860
  */
7810
7861
  toAnthropicRole(role) {
7811
7862
  if (role === "model" || role === "assistant") return "assistant";
7812
7863
  return "user";
7813
7864
  }
7814
7865
  /**
7815
- * Convert Anthropic stop reason to ADK finish reason
7866
+ * Convert Anthropic stop reason to ADK-TS finish reason
7816
7867
  */
7817
7868
  toAdkFinishReason(anthropicStopReason) {
7818
7869
  if (["end_turn", "stop_sequence", "tool_use"].includes(
@@ -8407,7 +8458,10 @@ var OpenAiLlm = class extends BaseLlm {
8407
8458
  functionCall: {
8408
8459
  id: toolCall.id,
8409
8460
  name: toolCall.function.name,
8410
- args: JSON.parse(toolCall.function.arguments || "{}")
8461
+ args: safeParseToolArgs(
8462
+ toolCall.function.arguments,
8463
+ this.logger
8464
+ )
8411
8465
  }
8412
8466
  });
8413
8467
  }
@@ -8500,7 +8554,7 @@ var OpenAiLlm = class extends BaseLlm {
8500
8554
  functionCall: {
8501
8555
  id: toolCall.id || "",
8502
8556
  name: toolCall.function.name,
8503
- args: JSON.parse(toolCall.function.arguments || "{}")
8557
+ args: safeParseToolArgs(toolCall.function.arguments, this.logger)
8504
8558
  }
8505
8559
  });
8506
8560
  }
@@ -8519,7 +8573,7 @@ var OpenAiLlm = class extends BaseLlm {
8519
8573
  });
8520
8574
  }
8521
8575
  /**
8522
- * Convert OpenAI message to ADK LlmResponse
8576
+ * Convert OpenAI message to ADK-TS LlmResponse
8523
8577
  */
8524
8578
  openAiMessageToLlmResponse(choice, usage) {
8525
8579
  const message = choice.message;
@@ -8534,7 +8588,7 @@ var OpenAiLlm = class extends BaseLlm {
8534
8588
  functionCall: {
8535
8589
  id: toolCall.id,
8536
8590
  name: toolCall.function.name,
8537
- args: JSON.parse(toolCall.function.arguments || "{}")
8591
+ args: safeParseToolArgs(toolCall.function.arguments, this.logger)
8538
8592
  }
8539
8593
  });
8540
8594
  }
@@ -8554,7 +8608,7 @@ var OpenAiLlm = class extends BaseLlm {
8554
8608
  });
8555
8609
  }
8556
8610
  /**
8557
- * Convert ADK Content to OpenAI ChatCompletionMessage
8611
+ * Convert ADK-TS Content to OpenAI ChatCompletionMessage
8558
8612
  */
8559
8613
  contentToOpenAiMessage(content) {
8560
8614
  const role = this.toOpenAiRole(content.role);
@@ -8610,7 +8664,7 @@ var OpenAiLlm = class extends BaseLlm {
8610
8664
  };
8611
8665
  }
8612
8666
  /**
8613
- * Convert ADK Part to OpenAI message content
8667
+ * Convert ADK-TS Part to OpenAI message content
8614
8668
  */
8615
8669
  partToOpenAiContent(part) {
8616
8670
  if (part.text) {
@@ -8667,7 +8721,7 @@ var OpenAiLlm = class extends BaseLlm {
8667
8721
  return transformedSchema;
8668
8722
  }
8669
8723
  /**
8670
- * Convert ADK function declaration to OpenAI tool
8724
+ * Convert ADK-TS function declaration to OpenAI tool
8671
8725
  */
8672
8726
  functionDeclarationToOpenAiTool(functionDeclaration) {
8673
8727
  return {
@@ -8682,7 +8736,7 @@ var OpenAiLlm = class extends BaseLlm {
8682
8736
  };
8683
8737
  }
8684
8738
  /**
8685
- * Convert ADK role to OpenAI role format
8739
+ * Convert ADK-TS role to OpenAI role format
8686
8740
  */
8687
8741
  toOpenAiRole(role) {
8688
8742
  if (role === "model") {
@@ -8694,7 +8748,7 @@ var OpenAiLlm = class extends BaseLlm {
8694
8748
  return "user";
8695
8749
  }
8696
8750
  /**
8697
- * Convert OpenAI finish reason to ADK finish reason
8751
+ * Convert OpenAI finish reason to ADK-TS finish reason
8698
8752
  */
8699
8753
  toAdkFinishReason(openaiFinishReason) {
8700
8754
  switch (openaiFinishReason) {
@@ -9026,7 +9080,7 @@ var ReadonlyContext = class {
9026
9080
  // src/agents/callback-context.ts
9027
9081
  var CallbackContext = class extends ReadonlyContext {
9028
9082
  /**
9029
- * TODO: make this public for Agent Development Kit, but private for users.
9083
+ * TODO: make this public for ADK-TS, but private for users.
9030
9084
  */
9031
9085
  _eventActions;
9032
9086
  _state;
@@ -9102,7 +9156,7 @@ var ToolContext = class extends CallbackContext {
9102
9156
  /**
9103
9157
  * The function call id of the current tool call. This id was
9104
9158
  * returned in the function call event from LLM to identify a function call.
9105
- * If LLM didn't return this id, ADK will assign one to it. This id is used
9159
+ * If LLM didn't return this id, ADK-TS will assign one to it. This id is used
9106
9160
  * to map function call response to the original function call.
9107
9161
  */
9108
9162
  functionCallId;
@@ -9578,7 +9632,7 @@ function mergeParallelFunctionResponseEvents(functionResponseEvents) {
9578
9632
  }
9579
9633
  mergedActions.requestedAuthConfigs = mergedRequestedAuthConfigs;
9580
9634
  const mergedEvent = new Event({
9581
- invocationId: Event.newId(),
9635
+ invocationId: baseEvent.invocationId,
9582
9636
  author: baseEvent.author,
9583
9637
  branch: baseEvent.branch,
9584
9638
  content: { role: "user", parts: mergedParts },
@@ -9630,7 +9684,7 @@ var EnhancedAuthConfig = class {
9630
9684
  rawAuthCredential;
9631
9685
  /**
9632
9686
  * Exchanged auth credential after processing
9633
- * Filled by ADK and client working together
9687
+ * Filled by ADK-TS and client working together
9634
9688
  */
9635
9689
  exchangedAuthCredential;
9636
9690
  /**
@@ -10501,7 +10555,7 @@ var FileOperationsTool = class extends BaseTool {
10501
10555
  async runAsync(args, _context) {
10502
10556
  try {
10503
10557
  const resolvedPath = this.resolvePath(args.filepath);
10504
- this.validatePath(resolvedPath);
10558
+ await this.validatePath(resolvedPath);
10505
10559
  const encoding = args.encoding || "utf8";
10506
10560
  switch (args.operation) {
10507
10561
  case "read":
@@ -10543,15 +10597,38 @@ var FileOperationsTool = class extends BaseTool {
10543
10597
  return import_node_path3.default.isAbsolute(filepath) ? filepath : import_node_path3.default.resolve(this.basePath, filepath);
10544
10598
  }
10545
10599
  /**
10546
- * Validate that a path is within the base path for security
10600
+ * Validate that a path is within the base path for security.
10601
+ * Resolves symlinks to prevent symlink escape attacks.
10547
10602
  */
10548
- validatePath(filepath) {
10549
- const normalizedPath = import_node_path3.default.normalize(filepath);
10550
- const normalizedBasePath = import_node_path3.default.normalize(this.basePath);
10551
- if (!normalizedPath.startsWith(normalizedBasePath)) {
10552
- throw new Error(
10553
- `Access denied: Can't access paths outside the base directory`
10554
- );
10603
+ async validatePath(filepath) {
10604
+ const realBasePath = await import_promises.default.realpath(this.basePath);
10605
+ const isWithinBase = (p, base) => p === base || p.startsWith(base + import_node_path3.default.sep);
10606
+ try {
10607
+ const realPath = await import_promises.default.realpath(filepath);
10608
+ if (!isWithinBase(realPath, realBasePath)) {
10609
+ throw new Error(
10610
+ "Access denied: Can't access paths outside the base directory"
10611
+ );
10612
+ }
10613
+ } catch (error) {
10614
+ if (error instanceof Error && "code" in error && error.code === "ENOENT") {
10615
+ const parentDir = import_node_path3.default.dirname(filepath);
10616
+ let realParent;
10617
+ try {
10618
+ realParent = await import_promises.default.realpath(parentDir);
10619
+ } catch {
10620
+ throw new Error(
10621
+ "Access denied: Can't access paths outside the base directory"
10622
+ );
10623
+ }
10624
+ if (!isWithinBase(realParent, realBasePath)) {
10625
+ throw new Error(
10626
+ "Access denied: Can't access paths outside the base directory"
10627
+ );
10628
+ }
10629
+ } else {
10630
+ throw error;
10631
+ }
10555
10632
  }
10556
10633
  }
10557
10634
  /**
@@ -10649,7 +10726,7 @@ var FileOperationsTool = class extends BaseTool {
10649
10726
  const results = await Promise.all(
10650
10727
  entries.map(async (entry) => {
10651
10728
  const entryPath = import_node_path3.default.join(dirpath, entry.name);
10652
- const stats = await import_promises.default.stat(entryPath);
10729
+ const stats = await import_promises.default.lstat(entryPath);
10653
10730
  return {
10654
10731
  name: entry.name,
10655
10732
  path: entryPath,
@@ -10891,6 +10968,62 @@ var googleSearchArgsSchema = import_zod.z.object({
10891
10968
  // src/tools/common/http-request-tool.ts
10892
10969
  var import_genai8 = require("@google/genai");
10893
10970
  init_base_tool();
10971
+
10972
+ // src/tools/utils/url-validation.ts
10973
+ function validateUrlForFetch(urlString) {
10974
+ const url = new URL(urlString);
10975
+ if (url.protocol !== "http:" && url.protocol !== "https:") {
10976
+ throw new Error(
10977
+ `Blocked URL: only http and https protocols are allowed, got ${url.protocol}`
10978
+ );
10979
+ }
10980
+ const hostname = url.hostname.toLowerCase();
10981
+ if (hostname === "localhost" || hostname === "[::1]") {
10982
+ throw new Error("Blocked URL: localhost is not allowed");
10983
+ }
10984
+ const ipv4 = extractIPv4(hostname);
10985
+ if (ipv4 !== null && isPrivateIP(ipv4)) {
10986
+ throw new Error(
10987
+ "Blocked URL: private/internal IP addresses are not allowed"
10988
+ );
10989
+ }
10990
+ if (isPrivateIP(hostname)) {
10991
+ throw new Error(
10992
+ "Blocked URL: private/internal IP addresses are not allowed"
10993
+ );
10994
+ }
10995
+ return url;
10996
+ }
10997
+ function extractIPv4(hostname) {
10998
+ const bare = hostname.replace(/^\[|\]$/g, "");
10999
+ const dottedMatch = bare.match(
11000
+ /^::ffff:(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})$/i
11001
+ );
11002
+ if (dottedMatch) return dottedMatch[1];
11003
+ const hexMatch = bare.match(/^::ffff:([0-9a-f]{1,4}):([0-9a-f]{1,4})$/i);
11004
+ if (hexMatch) {
11005
+ const high = Number.parseInt(hexMatch[1], 16);
11006
+ const low = Number.parseInt(hexMatch[2], 16);
11007
+ return `${high >> 8 & 255}.${high & 255}.${low >> 8 & 255}.${low & 255}`;
11008
+ }
11009
+ return null;
11010
+ }
11011
+ function isPrivateIP(hostname) {
11012
+ const match = hostname.match(/^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/);
11013
+ if (!match) return false;
11014
+ const [, a, b] = match;
11015
+ const first = Number(a);
11016
+ const second = Number(b);
11017
+ if (first === 0) return true;
11018
+ if (first === 127) return true;
11019
+ if (first === 10) return true;
11020
+ if (first === 172 && second >= 16 && second <= 31) return true;
11021
+ if (first === 192 && second === 168) return true;
11022
+ if (first === 169 && second === 254) return true;
11023
+ return false;
11024
+ }
11025
+
11026
+ // src/tools/common/http-request-tool.ts
10894
11027
  var HttpRequestTool = class extends BaseTool {
10895
11028
  constructor() {
10896
11029
  super({
@@ -10953,7 +11086,7 @@ var HttpRequestTool = class extends BaseTool {
10953
11086
  params,
10954
11087
  timeout = 1e4
10955
11088
  } = args;
10956
- const urlObj = new URL(url);
11089
+ const urlObj = validateUrlForFetch(url);
10957
11090
  if (params) {
10958
11091
  Object.entries(params).forEach(([key, value]) => {
10959
11092
  urlObj.searchParams.append(key, value);
@@ -10967,7 +11100,8 @@ var HttpRequestTool = class extends BaseTool {
10967
11100
  method,
10968
11101
  headers: requestHeaders,
10969
11102
  body,
10970
- signal: AbortSignal.timeout(timeout)
11103
+ signal: AbortSignal.timeout(timeout),
11104
+ redirect: "manual"
10971
11105
  };
10972
11106
  const response = await fetch(urlObj.toString(), options);
10973
11107
  const responseHeaders = {};
@@ -11775,16 +11909,16 @@ var BashTool = class _BashTool extends BaseTool {
11775
11909
  // filesystem formatting
11776
11910
  /dd\s+if=/,
11777
11911
  // disk operations
11778
- /wget.*\|\s*sh/,
11912
+ /wget.*\|\s*(sh|bash)/,
11779
11913
  // download and execute
11780
- /curl.*\|\s*bash/,
11914
+ /curl.*\|\s*(bash|sh)/,
11781
11915
  // download and execute
11782
11916
  /eval\s+['"`]/,
11783
11917
  // eval with strings
11784
- /base64.*\|\s*sh/,
11918
+ /base64.*\|\s*(sh|bash)/,
11785
11919
  // decode and execute
11786
- /nc\s+-.*e/,
11787
- // netcat reverse shell
11920
+ /(nc|ncat|netcat)\s+-.*e/,
11921
+ // netcat reverse shell (nc, ncat, netcat)
11788
11922
  /\/proc\/.*\/mem/,
11789
11923
  // memory access
11790
11924
  /iptables/,
@@ -11795,8 +11929,18 @@ var BashTool = class _BashTool extends BaseTool {
11795
11929
  // ownership changes
11796
11930
  /sudo/,
11797
11931
  // privilege escalation
11798
- /su\s+/
11932
+ /su\s+/,
11799
11933
  // user switching
11934
+ /python[23]?(\.\d+)?\s+-c\s/,
11935
+ // python interpreter execution (python, python3, python3.11, etc.)
11936
+ /node\s+(-e|--eval)[\s=]/,
11937
+ // node interpreter execution (-e and --eval)
11938
+ /perl\s+-e\s/,
11939
+ // perl interpreter execution
11940
+ /ruby\s+-e\s/,
11941
+ // ruby interpreter execution
11942
+ /php\s+-r\s/
11943
+ // php interpreter execution
11800
11944
  ];
11801
11945
  // Special characters that enable command chaining/injection
11802
11946
  static DANGEROUS_CHARS = /[;&|`$()<>]/;
@@ -12574,11 +12718,16 @@ var WebFetchTool = class extends BaseTool {
12574
12718
  }
12575
12719
  async runAsync(args, _context) {
12576
12720
  try {
12721
+ validateUrlForFetch(args.url);
12577
12722
  const response = await import_axios2.default.get(args.url, {
12578
12723
  timeout: 3e4,
12579
12724
  maxRedirects: 5,
12580
12725
  headers: {
12581
12726
  "User-Agent": "Mozilla/5.0 (compatible; ADK/1.0; +http://example.com)"
12727
+ },
12728
+ beforeRedirect: (options) => {
12729
+ const redirectUrl = typeof options.href === "string" ? options.href : `${options.protocol}//${options.hostname}${options.path}`;
12730
+ validateUrlForFetch(redirectUrl);
12582
12731
  }
12583
12732
  });
12584
12733
  const contentType = response.headers["content-type"] || "";
@@ -12831,7 +12980,7 @@ var tavilySearchResultSchema = import_zod2.z.object({
12831
12980
  var tavilySearchResponseSchema = import_zod2.z.object({
12832
12981
  query: import_zod2.z.string(),
12833
12982
  results: import_zod2.z.array(tavilySearchResultSchema),
12834
- answer: import_zod2.z.string().optional(),
12983
+ answer: import_zod2.z.string().nullable().optional(),
12835
12984
  images: import_zod2.z.array(import_zod2.z.object({ url: import_zod2.z.string(), description: import_zod2.z.string().optional() })).optional(),
12836
12985
  auto_parameters: import_zod2.z.record(import_zod2.z.any(), import_zod2.z.string()).optional(),
12837
12986
  response_time: import_zod2.z.number(),
@@ -12988,7 +13137,7 @@ var McpSamplingHandler = class {
12988
13137
  "INVALID_REQUEST_ERROR" /* INVALID_REQUEST_ERROR */
12989
13138
  );
12990
13139
  }
12991
- this.logger.debug("Converting MCP request to ADK format");
13140
+ this.logger.debug("Converting MCP request to ADK-TS format");
12992
13141
  const adkContents = this.convertMcpMessagesToADK(
12993
13142
  mcpParams.messages,
12994
13143
  mcpParams.systemPrompt
@@ -13002,9 +13151,9 @@ var McpSamplingHandler = class {
13002
13151
  maxOutputTokens: mcpParams.maxTokens
13003
13152
  }
13004
13153
  });
13005
- this.logger.debug("Calling ADK sampling handler");
13154
+ this.logger.debug("Calling ADK-TS sampling handler");
13006
13155
  const adkResponse = await this.samplingHandler(adkRequest);
13007
- this.logger.debug("Converting ADK response to MCP format");
13156
+ this.logger.debug("Converting ADK-TS response to MCP format");
13008
13157
  const mcpResponse = this.convertADKResponseToMcp(
13009
13158
  adkResponse,
13010
13159
  requestModel
@@ -13034,7 +13183,7 @@ var McpSamplingHandler = class {
13034
13183
  }
13035
13184
  }
13036
13185
  /**
13037
- * Convert MCP messages to ADK Content format
13186
+ * Convert MCP messages to ADK-TS Content format
13038
13187
  */
13039
13188
  convertMcpMessagesToADK(mcpMessages, systemPrompt) {
13040
13189
  const contents = [];
@@ -13052,7 +13201,7 @@ var McpSamplingHandler = class {
13052
13201
  return contents;
13053
13202
  }
13054
13203
  /**
13055
- * Convert a single MCP message to ADK Content format
13204
+ * Convert a single MCP message to ADK-TS Content format
13056
13205
  */
13057
13206
  convertSingleMcpMessageToADK(mcpMessage) {
13058
13207
  const adkRole = mcpMessage.role === "assistant" ? "model" : "user";
@@ -13067,7 +13216,7 @@ var McpSamplingHandler = class {
13067
13216
  return adkContent;
13068
13217
  }
13069
13218
  /**
13070
- * Convert MCP message content to ADK parts format
13219
+ * Convert MCP message content to ADK-TS parts format
13071
13220
  */
13072
13221
  convertMcpContentToADKParts(mcpContent) {
13073
13222
  const safeText = (value) => typeof value === "string" ? value : "";
@@ -13120,7 +13269,7 @@ var McpSamplingHandler = class {
13120
13269
  }
13121
13270
  }
13122
13271
  /**
13123
- * Convert ADK response to MCP response format
13272
+ * Convert ADK-TS response to MCP response format
13124
13273
  */
13125
13274
  convertADKResponseToMcp(adkResponse, model) {
13126
13275
  let responseText = "";
@@ -13141,7 +13290,7 @@ var McpSamplingHandler = class {
13141
13290
  model,
13142
13291
  // Use the model from the request
13143
13292
  role: "assistant",
13144
- // ADK responses are always from assistant
13293
+ // ADK-TS responses are always from assistant
13145
13294
  content: {
13146
13295
  type: "text",
13147
13296
  text: responseText
@@ -13151,11 +13300,11 @@ var McpSamplingHandler = class {
13151
13300
  return mcpResponse;
13152
13301
  }
13153
13302
  /**
13154
- * Update the ADK handler
13303
+ * Update the ADK-TS handler
13155
13304
  */
13156
13305
  updateHandler(handler) {
13157
13306
  this.samplingHandler = handler;
13158
- this.logger.debug("ADK sampling handler updated");
13307
+ this.logger.debug("ADK-TS sampling handler updated");
13159
13308
  }
13160
13309
  };
13161
13310
  function createSamplingHandler(handler) {
@@ -13428,13 +13577,13 @@ var McpClientService = class {
13428
13577
  }
13429
13578
  }
13430
13579
  /**
13431
- * Set a new ADK sampling handler
13580
+ * Set a new ADK-TS sampling handler
13432
13581
  */
13433
13582
  setSamplingHandler(handler) {
13434
13583
  this.mcpSamplingHandler = new McpSamplingHandler(handler);
13435
13584
  if (this.client) {
13436
13585
  this.setupSamplingHandler(this.client).catch((error) => {
13437
- this.logger.error("Failed to update ADK sampling handler:", error);
13586
+ this.logger.error("Failed to update ADK-TS sampling handler:", error);
13438
13587
  });
13439
13588
  }
13440
13589
  }
@@ -14017,6 +14166,9 @@ var McpToolset = class {
14017
14166
  }
14018
14167
  return true;
14019
14168
  }
14169
+ isCacheEnabled() {
14170
+ return this.config.cacheConfig?.enabled !== false;
14171
+ }
14020
14172
  /**
14021
14173
  * Initializes the client service and establishes a connection.
14022
14174
  */
@@ -14035,9 +14187,9 @@ var McpToolset = class {
14035
14187
  }
14036
14188
  /**
14037
14189
  * Set a sampling handler for this MCP toolset.
14038
- * This allows MCP servers to request LLM completions through your ADK agent.
14190
+ * This allows MCP servers to request LLM completions through your ADK-TS agent.
14039
14191
  *
14040
- * @param handler - ADK sampling handler that receives ADK-formatted messages
14192
+ * @param handler - ADK-TS sampling handler that receives ADK-TS-formatted messages
14041
14193
  */
14042
14194
  setSamplingHandler(handler) {
14043
14195
  if (!this.clientService) {
@@ -14071,7 +14223,7 @@ var McpToolset = class {
14071
14223
  "resource_closed_error" /* RESOURCE_CLOSED_ERROR */
14072
14224
  );
14073
14225
  }
14074
- if (this.tools.length > 0 && !this.config.cacheConfig?.enabled === false) {
14226
+ if (this.tools.length > 0 && this.isCacheEnabled()) {
14075
14227
  return this.tools;
14076
14228
  }
14077
14229
  if (!this.clientService) {
@@ -14100,7 +14252,7 @@ var McpToolset = class {
14100
14252
  }
14101
14253
  }
14102
14254
  }
14103
- if (this.config.cacheConfig?.enabled !== false) {
14255
+ if (this.isCacheEnabled()) {
14104
14256
  this.tools = tools;
14105
14257
  }
14106
14258
  return tools;
@@ -14117,7 +14269,7 @@ var McpToolset = class {
14117
14269
  }
14118
14270
  }
14119
14271
  /**
14120
- * Converts ADK tools to MCP tool format for bidirectional support
14272
+ * Converts ADK-TS tools to MCP tool format for bidirectional support
14121
14273
  */
14122
14274
  convertADKToolsToMCP(tools) {
14123
14275
  return tools.map((tool) => adkToMcpToolType(tool));
@@ -14810,10 +14962,7 @@ var CodeExecutionUtils = class _CodeExecutionUtils {
14810
14962
  * Gets the file content as a base64-encoded string
14811
14963
  */
14812
14964
  static getEncodedFileContent(data) {
14813
- let decodedData;
14814
- if (data instanceof ArrayBuffer) {
14815
- decodedData = new TextDecoder().decode(data);
14816
- }
14965
+ const decodedData = data instanceof ArrayBuffer ? new TextDecoder().decode(data) : data;
14817
14966
  if (_CodeExecutionUtils.isBase64Encoded(decodedData)) {
14818
14967
  return decodedData;
14819
14968
  }
@@ -16776,7 +16925,7 @@ var BaseAgent = class {
16776
16925
  }
16777
16926
  /**
16778
16927
  * The resolved beforeAgentCallback field as a list of SingleAgentCallback.
16779
- * This method is only for use by Agent Development Kit.
16928
+ * This method is only for use by ADK-TS.
16780
16929
  */
16781
16930
  get canonicalBeforeAgentCallbacks() {
16782
16931
  if (!this.beforeAgentCallback) {
@@ -16789,7 +16938,7 @@ var BaseAgent = class {
16789
16938
  }
16790
16939
  /**
16791
16940
  * The resolved afterAgentCallback field as a list of SingleAgentCallback.
16792
- * This method is only for use by Agent Development Kit.
16941
+ * This method is only for use by ADK-TS.
16793
16942
  */
16794
16943
  get canonicalAfterAgentCallbacks() {
16795
16944
  if (!this.afterAgentCallback) {
@@ -17091,7 +17240,7 @@ var LlmAgent = class _LlmAgent extends BaseAgent {
17091
17240
  }
17092
17241
  /**
17093
17242
  * The resolved model field as BaseLLM
17094
- * This method is only for use by Agent Development Kit
17243
+ * This method is only for use by ADK-TS
17095
17244
  */
17096
17245
  get canonicalModel() {
17097
17246
  if (typeof this.model === "string") {
@@ -17116,7 +17265,7 @@ var LlmAgent = class _LlmAgent extends BaseAgent {
17116
17265
  }
17117
17266
  /**
17118
17267
  * The resolved instruction field to construct instruction for this agent
17119
- * This method is only for use by Agent Development Kit
17268
+ * This method is only for use by ADK-TS
17120
17269
  */
17121
17270
  async canonicalInstruction(ctx) {
17122
17271
  if (typeof this.instruction === "string") {
@@ -17127,7 +17276,7 @@ var LlmAgent = class _LlmAgent extends BaseAgent {
17127
17276
  }
17128
17277
  /**
17129
17278
  * The resolved global_instruction field to construct global instruction
17130
- * This method is only for use by Agent Development Kit
17279
+ * This method is only for use by ADK-TS
17131
17280
  */
17132
17281
  async canonicalGlobalInstruction(ctx) {
17133
17282
  if (typeof this.globalInstruction === "string") {
@@ -17138,7 +17287,7 @@ var LlmAgent = class _LlmAgent extends BaseAgent {
17138
17287
  }
17139
17288
  /**
17140
17289
  * The resolved tools field as a list of BaseTool based on the context
17141
- * This method is only for use by Agent Development Kit
17290
+ * This method is only for use by ADK-TS
17142
17291
  */
17143
17292
  async canonicalTools(_ctx) {
17144
17293
  const resolvedTools = [];
@@ -18543,6 +18692,7 @@ var LangGraphAgent = class extends BaseAgent {
18543
18692
  * Core logic to run this agent via text-based conversation.
18544
18693
  */
18545
18694
  async *runAsyncImpl(context4) {
18695
+ this.results = [];
18546
18696
  this.logger.debug(
18547
18697
  `Starting graph execution from root node "${this.rootNode}"`
18548
18698
  );
@@ -18734,7 +18884,7 @@ function createBranchContextForSubAgent(agent, subAgent, invocationContext) {
18734
18884
  agent: subAgent,
18735
18885
  userContent: invocationContext.userContent,
18736
18886
  session: invocationContext.session,
18737
- endInvocation: invocationContext.endInvocation,
18887
+ invocationFlags: invocationContext.getInvocationFlags(),
18738
18888
  liveRequestQueue: invocationContext.liveRequestQueue,
18739
18889
  activeStreamingTools: invocationContext.activeStreamingTools,
18740
18890
  transcriptionCache: invocationContext.transcriptionCache,
@@ -19700,8 +19850,29 @@ var GcsArtifactService = class {
19700
19850
  version
19701
19851
  );
19702
19852
  const blob = this.bucket.file(blobName);
19703
- await blob.save(artifact.inlineData.data, {
19704
- contentType: artifact.inlineData.mimeType,
19853
+ let data;
19854
+ let contentType;
19855
+ let partType;
19856
+ if (artifact.text !== void 0) {
19857
+ data = artifact.text;
19858
+ contentType = "text/plain";
19859
+ partType = "text";
19860
+ } else if (artifact.inlineData) {
19861
+ data = artifact.inlineData.data;
19862
+ contentType = artifact.inlineData.mimeType;
19863
+ partType = "inlineData";
19864
+ } else if (artifact.fileData) {
19865
+ data = artifact.fileData.fileUri;
19866
+ contentType = artifact.fileData.mimeType || "application/octet-stream";
19867
+ partType = "fileData";
19868
+ } else {
19869
+ throw new Error(
19870
+ "Unsupported artifact Part type: must have text, inlineData, or fileData"
19871
+ );
19872
+ }
19873
+ await blob.save(data, {
19874
+ contentType,
19875
+ metadata: { partType },
19705
19876
  preconditionOpts: { ifGenerationMatch: 0 }
19706
19877
  });
19707
19878
  return version;
@@ -19735,12 +19906,25 @@ var GcsArtifactService = class {
19735
19906
  if (!artifactBuffer) {
19736
19907
  return null;
19737
19908
  }
19738
- const part = {
19739
- inlineData: {
19740
- data: artifactBuffer.toString(),
19741
- mimeType: metadata.contentType || "application/octet-stream"
19742
- }
19743
- };
19909
+ const partType = metadata.metadata?.partType;
19910
+ let part;
19911
+ if (partType === "text") {
19912
+ part = { text: artifactBuffer.toString() };
19913
+ } else if (partType === "fileData") {
19914
+ part = {
19915
+ fileData: {
19916
+ fileUri: artifactBuffer.toString(),
19917
+ mimeType: metadata.contentType || "application/octet-stream"
19918
+ }
19919
+ };
19920
+ } else {
19921
+ part = {
19922
+ inlineData: {
19923
+ data: artifactBuffer.toString(),
19924
+ mimeType: metadata.contentType || "application/octet-stream"
19925
+ }
19926
+ };
19927
+ }
19744
19928
  return part;
19745
19929
  } catch (error) {
19746
19930
  if (error?.code === 404) {
@@ -19864,7 +20048,7 @@ var EvalResult = class {
19864
20048
  this.evalSetResultName = init.evalSetResultName;
19865
20049
  this.evalSetId = init.evalSetId || "";
19866
20050
  this.evalCaseResults = init.evalCaseResults || [];
19867
- this.creationTimestamp = init.creationTimestamp || Date.now() / 1e3;
20051
+ this.creationTimestamp = init.creationTimestamp || Date.now();
19868
20052
  }
19869
20053
  };
19870
20054
 
@@ -19892,6 +20076,8 @@ var BaseEvalService = class {
19892
20076
  };
19893
20077
 
19894
20078
  // src/evaluation/vertex-ai-eval-facade.ts
20079
+ var import_google_auth_library = require("google-auth-library");
20080
+ var import_axios4 = __toESM(require("axios"));
19895
20081
  var ERROR_MESSAGE_SUFFIX = `
19896
20082
  You should specify both project id and location. This metric uses Vertex Gen AI
19897
20083
  Eval SDK, and it requires google cloud credentials.
@@ -19902,6 +20088,28 @@ the template below:
19902
20088
  process.env.GOOGLE_CLOUD_LOCATION = <LOCATION>
19903
20089
  process.env.GOOGLE_CLOUD_PROJECT = <PROJECT ID>
19904
20090
  `;
20091
+ var VERTEX_AI_EVAL_SCOPES = [
20092
+ "https://www.googleapis.com/auth/cloud-platform"
20093
+ ];
20094
+ var VERTEX_AI_METRIC_KEYS = {
20095
+ ["response_evaluation_score" /* RESPONSE_EVALUATION_SCORE */]: {
20096
+ inputKey: "coherence_input",
20097
+ resultKey: "coherenceResult"
20098
+ },
20099
+ ["safety_v1" /* SAFETY_V1 */]: {
20100
+ inputKey: "safety_input",
20101
+ resultKey: "safetyResult"
20102
+ }
20103
+ };
20104
+ function getMetricKeys(metric) {
20105
+ const keys = VERTEX_AI_METRIC_KEYS[metric];
20106
+ if (!keys) {
20107
+ throw new Error(
20108
+ `Metric "${metric}" is not supported by Vertex AI evaluation.`
20109
+ );
20110
+ }
20111
+ return keys;
20112
+ }
19905
20113
  var VertexAiEvalFacade = class _VertexAiEvalFacade {
19906
20114
  threshold;
19907
20115
  metricName;
@@ -19926,8 +20134,8 @@ var VertexAiEvalFacade = class _VertexAiEvalFacade {
19926
20134
  };
19927
20135
  try {
19928
20136
  const evalCaseResult = await _VertexAiEvalFacade._performEval(
19929
- [evalCase],
19930
- [this.metricName]
20137
+ evalCase,
20138
+ this.metricName
19931
20139
  );
19932
20140
  const score = this._getScore(evalCaseResult);
19933
20141
  perInvocationResults.push({
@@ -19971,8 +20179,9 @@ var VertexAiEvalFacade = class _VertexAiEvalFacade {
19971
20179
  return "";
19972
20180
  }
19973
20181
  _getScore(evalResult) {
19974
- if (evalResult?.summaryMetrics?.[0]?.meanScore !== void 0 && typeof evalResult.summaryMetrics[0].meanScore === "number" && !Number.isNaN(evalResult.summaryMetrics[0].meanScore)) {
19975
- return evalResult.summaryMetrics[0].meanScore;
20182
+ const meanScore = evalResult?.summaryMetrics?.[0]?.meanScore;
20183
+ if (typeof meanScore === "number" && !Number.isNaN(meanScore)) {
20184
+ return meanScore;
19976
20185
  }
19977
20186
  return void 0;
19978
20187
  }
@@ -19982,7 +20191,7 @@ var VertexAiEvalFacade = class _VertexAiEvalFacade {
19982
20191
  }
19983
20192
  return 3 /* NOT_EVALUATED */;
19984
20193
  }
19985
- static async _performEval(dataset, metrics3) {
20194
+ static async _performEval(evalCase, metric) {
19986
20195
  const projectId = process.env.GOOGLE_CLOUD_PROJECT;
19987
20196
  const location = process.env.GOOGLE_CLOUD_LOCATION;
19988
20197
  if (!projectId) {
@@ -19991,13 +20200,50 @@ var VertexAiEvalFacade = class _VertexAiEvalFacade {
19991
20200
  if (!location) {
19992
20201
  throw new Error(`Missing location. ${ERROR_MESSAGE_SUFFIX}`);
19993
20202
  }
19994
- console.warn(
19995
- "Vertex AI evaluation is not fully implemented. Using mock response."
19996
- );
20203
+ const auth = new import_google_auth_library.GoogleAuth({ scopes: VERTEX_AI_EVAL_SCOPES });
20204
+ const accessToken = await auth.getAccessToken();
20205
+ if (!accessToken) {
20206
+ throw new Error(
20207
+ "Failed to obtain Google Cloud access token. Ensure Application Default Credentials are configured (e.g. run 'gcloud auth application-default login')."
20208
+ );
20209
+ }
20210
+ const { inputKey, resultKey } = getMetricKeys(metric);
20211
+ const url = `https://${location}-aiplatform.googleapis.com/v1beta1/projects/${projectId}/locations/${location}:evaluateInstances`;
20212
+ const instance = {
20213
+ prediction: evalCase.response
20214
+ };
20215
+ if (metric === "response_evaluation_score" /* RESPONSE_EVALUATION_SCORE */) {
20216
+ instance.reference = evalCase.reference;
20217
+ }
20218
+ const requestBody = {
20219
+ [inputKey]: {
20220
+ metric_spec: {},
20221
+ instance
20222
+ }
20223
+ };
20224
+ let responseData;
20225
+ try {
20226
+ const response = await import_axios4.default.post(url, requestBody, {
20227
+ headers: {
20228
+ Authorization: `Bearer ${accessToken}`,
20229
+ "Content-Type": "application/json"
20230
+ }
20231
+ });
20232
+ responseData = response.data;
20233
+ } catch (error) {
20234
+ if (import_axios4.default.isAxiosError(error)) {
20235
+ const detail = error.response?.data ? JSON.stringify(error.response.data) : "";
20236
+ throw new Error(
20237
+ `Vertex AI evaluation API request failed: ${error.message}${detail ? ` \u2014 ${detail}` : ""}`
20238
+ );
20239
+ }
20240
+ throw error;
20241
+ }
20242
+ const score = responseData?.[resultKey]?.score;
19997
20243
  return {
19998
20244
  summaryMetrics: [
19999
20245
  {
20000
- meanScore: Math.random() * 0.5 + 0.5
20246
+ meanScore: typeof score === "number" ? score : void 0
20001
20247
  }
20002
20248
  ]
20003
20249
  };
@@ -20453,9 +20699,13 @@ var LocalEvalService = class extends BaseEvalService {
20453
20699
  super();
20454
20700
  this.agent = agent;
20455
20701
  this.parallelism = parallelism;
20456
- this.initializeRunner();
20702
+ this.readyPromise = this.initializeRunner();
20457
20703
  }
20458
20704
  runner;
20705
+ readyPromise;
20706
+ ensureReady() {
20707
+ return this.readyPromise;
20708
+ }
20459
20709
  async initializeRunner() {
20460
20710
  if ("ask" in this.agent) {
20461
20711
  this.runner = this.agent;
@@ -20554,9 +20804,7 @@ var LocalEvalService = class extends BaseEvalService {
20554
20804
  }
20555
20805
  async runInference(evalCase) {
20556
20806
  const results = [];
20557
- if (!this.runner) {
20558
- await this.initializeRunner();
20559
- }
20807
+ await this.ensureReady();
20560
20808
  if (evalCase.sessionInput) {
20561
20809
  try {
20562
20810
  if (this.runner.initializeSession) {
@@ -23114,6 +23362,7 @@ var import_kysely = require("kysely");
23114
23362
  var DatabaseSessionService = class extends BaseSessionService {
23115
23363
  db;
23116
23364
  initialized = false;
23365
+ initPromise = null;
23117
23366
  constructor(config) {
23118
23367
  super();
23119
23368
  this.db = config.db;
@@ -23124,12 +23373,26 @@ var DatabaseSessionService = class extends BaseSessionService {
23124
23373
  }
23125
23374
  }
23126
23375
  /**
23127
- * Initialize the database by creating required tables if they don't exist
23376
+ * Initialize the database by creating required tables if they don't exist.
23377
+ * Uses promise deduplication so concurrent callers share a single initialization.
23128
23378
  */
23129
- async initializeDatabase() {
23379
+ initializeDatabase() {
23130
23380
  if (this.initialized) {
23131
- return;
23381
+ return Promise.resolve();
23382
+ }
23383
+ if (this.initPromise) {
23384
+ return this.initPromise;
23132
23385
  }
23386
+ const promise = this._doInitialize();
23387
+ this.initPromise = promise;
23388
+ promise.catch(() => {
23389
+ if (this.initPromise === promise) {
23390
+ this.initPromise = null;
23391
+ }
23392
+ });
23393
+ return promise;
23394
+ }
23395
+ async _doInitialize() {
23133
23396
  try {
23134
23397
  await this.db.schema.createTable("sessions").ifNotExists().addColumn("id", "varchar(128)", (col) => col.notNull()).addColumn("app_name", "varchar(128)", (col) => col.notNull()).addColumn("user_id", "varchar(128)", (col) => col.notNull()).addColumn("state", "text", (col) => col.defaultTo("{}")).addColumn(
23135
23398
  "create_time",
@@ -23396,7 +23659,8 @@ var DatabaseSessionService = class extends BaseSessionService {
23396
23659
  session.lastUpdateTime = this.timestampToUnixSeconds(
23397
23660
  updatedSession.update_time
23398
23661
  );
23399
- super.appendEvent(session, event);
23662
+ this.updateSessionState(session, event);
23663
+ session.events.push(event);
23400
23664
  return event;
23401
23665
  });
23402
23666
  }